Salome HOME
Tools for partitioning and neighbor computation
[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 "MEDCouplingFieldDouble.hxx"
24 #include "MEDCouplingSkyLineArray.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DiameterCalculator.hxx"
33 #include "DirectedBoundingBox.hxx"
34 #include "InterpKernelMatrixTools.hxx"
35 #include "InterpKernelMeshQuality.hxx"
36 #include "InterpKernelCellSimplify.hxx"
37 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
38 #include "InterpKernelAutoPtr.hxx"
39 #include "InterpKernelGeo2DNode.hxx"
40 #include "InterpKernelGeo2DEdgeLin.hxx"
41 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
42 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
43
44 #include <sstream>
45 #include <fstream>
46 #include <numeric>
47 #include <cstring>
48 #include <limits>
49 #include <list>
50
51 using namespace MEDCoupling;
52
53 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
54
55 /// @cond INTERNAL
56 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 };
57 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};
58 /// @endcond
59
60 MEDCouplingUMesh *MEDCouplingUMesh::New()
61 {
62   return new MEDCouplingUMesh;
63 }
64
65 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
66 {
67   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
68   ret->setName(meshName);
69   ret->setMeshDimension(meshDim);
70   return ret;
71 }
72
73 /*!
74  * Returns a new MEDCouplingUMesh which is a full copy of \a this one. No data is shared
75  * between \a this and the new mesh.
76  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
77  *          delete this mesh using decrRef() as it is no more needed. 
78  */
79 MEDCouplingUMesh *MEDCouplingUMesh::deepCopy() const
80 {
81   return clone(true);
82 }
83
84
85 /*!
86  * Returns a new MEDCouplingUMesh which is a copy of \a this one.
87  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
88  * this mesh are shared by the new mesh.
89  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
90  *          delete this mesh using decrRef() as it is no more needed. 
91  */
92 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
93 {
94   return new MEDCouplingUMesh(*this,recDeepCpy);
95 }
96
97 /*!
98  * This method behaves mostly like MEDCouplingUMesh::deepCopy method, except that only nodal connectivity arrays are deeply copied.
99  * The coordinates are shared between \a this and the returned instance.
100  * 
101  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
102  * \sa MEDCouplingUMesh::deepCopy
103  */
104 MEDCouplingUMesh *MEDCouplingUMesh::deepCopyConnectivityOnly() const
105 {
106   checkConnectivityFullyDefined();
107   MCAuto<MEDCouplingUMesh> ret=clone(false);
108   MCAuto<DataArrayInt> c(getNodalConnectivity()->deepCopy()),ci(getNodalConnectivityIndex()->deepCopy());
109   ret->setConnectivity(c,ci);
110   return ret.retn();
111 }
112
113 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
114 {
115   if(!other)
116     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
117   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
118   if(!otherC)
119     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
120   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
121   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
122 }
123
124 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
125 {
126   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
127   return ret;
128 }
129
130 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
131 {
132   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
133   ret.push_back(_nodal_connec);
134   ret.push_back(_nodal_connec_index);
135   return ret;
136 }
137
138 void MEDCouplingUMesh::updateTime() const
139 {
140   MEDCouplingPointSet::updateTime();
141   if(_nodal_connec)
142     {
143       updateTimeWith(*_nodal_connec);
144     }
145   if(_nodal_connec_index)
146     {
147       updateTimeWith(*_nodal_connec_index);
148     }
149 }
150
151 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
152 {
153 }
154
155 /*!
156  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
157  * then \a this mesh is most probably is writable, exchangeable and available for most
158  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
159  * this method to check that all is in order with \a this mesh.
160  *  \throw If the mesh dimension is not set.
161  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
162  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
163  *  \throw If the connectivity data array has more than one component.
164  *  \throw If the connectivity data array has a named component.
165  *  \throw If the connectivity index data array has more than one component.
166  *  \throw If the connectivity index data array has a named component.
167  */
168 void MEDCouplingUMesh::checkConsistencyLight() const
169 {
170   if(_mesh_dim<-1)
171     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
172   if(_mesh_dim!=-1)
173     MEDCouplingPointSet::checkConsistencyLight();
174   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
175     {
176       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
177         {
178           std::ostringstream message;
179           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
180           throw INTERP_KERNEL::Exception(message.str().c_str());
181         }
182     }
183   if(_nodal_connec)
184     {
185       if(_nodal_connec->getNumberOfComponents()!=1)
186         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
187       if(_nodal_connec->getInfoOnComponent(0)!="")
188         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
189     }
190   else
191     if(_mesh_dim!=-1)
192       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
193   if(_nodal_connec_index)
194     {
195       if(_nodal_connec_index->getNumberOfComponents()!=1)
196         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
197       if(_nodal_connec_index->getInfoOnComponent(0)!="")
198         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
199     }
200   else
201     if(_mesh_dim!=-1)
202       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
203 }
204
205 /*!
206  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
207  * then \a this mesh is most probably is writable, exchangeable and available for all
208  * algorithms. <br> In addition to the checks performed by checkConsistencyLight(), this
209  * method thoroughly checks the nodal connectivity.
210  *  \param [in] eps - a not used parameter.
211  *  \throw If the mesh dimension is not set.
212  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
213  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
214  *  \throw If the connectivity data array has more than one component.
215  *  \throw If the connectivity data array has a named component.
216  *  \throw If the connectivity index data array has more than one component.
217  *  \throw If the connectivity index data array has a named component.
218  *  \throw If number of nodes defining an element does not correspond to the type of element.
219  *  \throw If the nodal connectivity includes an invalid node id.
220  */
221 void MEDCouplingUMesh::checkConsistency(double eps) const
222 {
223   checkConsistencyLight();
224   if(_mesh_dim==-1)
225     return ;
226   int meshDim=getMeshDimension();
227   int nbOfNodes=getNumberOfNodes();
228   int nbOfCells=getNumberOfCells();
229   const int *ptr=_nodal_connec->getConstPointer();
230   const int *ptrI=_nodal_connec_index->getConstPointer();
231   for(int i=0;i<nbOfCells;i++)
232     {
233       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
234       if((int)cm.getDimension()!=meshDim)
235         {
236           std::ostringstream oss;
237           oss << "MEDCouplingUMesh::checkConsistency : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
238           throw INTERP_KERNEL::Exception(oss.str());
239         }
240       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
241       if(!cm.isDynamic())
242         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
243           {
244             std::ostringstream oss;
245             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
246             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
247             throw INTERP_KERNEL::Exception(oss.str());
248           }
249       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
250         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
251           {
252             std::ostringstream oss;
253             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
254             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
255             throw INTERP_KERNEL::Exception(oss.str());
256           }
257       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
258         {
259           int nodeId=*w;
260           if(nodeId>=0)
261             {
262               if(nodeId>=nbOfNodes)
263                 {
264                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
265                   throw INTERP_KERNEL::Exception(oss.str());
266                 }
267             }
268           else if(nodeId<-1)
269             {
270               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
271               throw INTERP_KERNEL::Exception(oss.str());
272             }
273           else
274             {
275               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
276                 {
277                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
278                   throw INTERP_KERNEL::Exception(oss.str());
279                 }
280             }
281         }
282     }
283 }
284
285 /*!
286  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
287  * elements contained in the mesh. For more info on the mesh dimension see
288  * \ref MEDCouplingUMeshPage.
289  *  \param [in] meshDim - a new mesh dimension.
290  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
291  */
292 void MEDCouplingUMesh::setMeshDimension(int meshDim)
293 {
294   if(meshDim<-1 || meshDim>3)
295     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
296   _mesh_dim=meshDim;
297   declareAsNew();
298 }
299
300 /*!
301  * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
302  * the less will the library need to reallocate memory. If the number of cells to be inserted is not known simply put 0 to this parameter.
303  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
304  *
305  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
306  *
307  *  \if ENABLE_EXAMPLES
308  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
309  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
310  *  \endif
311  */
312 void MEDCouplingUMesh::allocateCells(int nbOfCells)
313 {
314   if(nbOfCells<0)
315     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
316   if(_nodal_connec_index)
317     {
318       _nodal_connec_index->decrRef();
319     }
320   if(_nodal_connec)
321     {
322       _nodal_connec->decrRef();
323     }
324   _nodal_connec_index=DataArrayInt::New();
325   _nodal_connec_index->reserve(nbOfCells+1);
326   _nodal_connec_index->pushBackSilent(0);
327   _nodal_connec=DataArrayInt::New();
328   _nodal_connec->reserve(2*nbOfCells);
329   _types.clear();
330   declareAsNew();
331 }
332
333 /*!
334  * Appends a cell to the connectivity array. For deeper understanding what is
335  * happening see \ref MEDCouplingUMeshNodalConnectivity.
336  *  \param [in] type - type of cell to add.
337  *  \param [in] size - number of nodes constituting this cell.
338  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
339  * 
340  *  \if ENABLE_EXAMPLES
341  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
342  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
343  *  \endif
344  */
345 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
346 {
347   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
348   if(_nodal_connec_index==0)
349     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
350   if((int)cm.getDimension()==_mesh_dim)
351     {
352       if(!cm.isDynamic())
353         if(size!=(int)cm.getNumberOfNodes())
354           {
355             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
356             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
357             throw INTERP_KERNEL::Exception(oss.str());
358           }
359       int idx=_nodal_connec_index->back();
360       int val=idx+size+1;
361       _nodal_connec_index->pushBackSilent(val);
362       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
363       _types.insert(type);
364     }
365   else
366     {
367       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
368       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
369       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
370       throw INTERP_KERNEL::Exception(oss.str());
371     }
372 }
373
374 /*!
375  * Compacts data arrays to release unused memory. This method is to be called after
376  * finishing cell insertion using \a this->insertNextCell().
377  * 
378  *  \if ENABLE_EXAMPLES
379  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
380  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
381  *  \endif
382  */
383 void MEDCouplingUMesh::finishInsertingCells()
384 {
385   _nodal_connec->pack();
386   _nodal_connec_index->pack();
387   _nodal_connec->declareAsNew();
388   _nodal_connec_index->declareAsNew();
389   updateTime();
390 }
391
392 /*!
393  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
394  * Useful for python users.
395  */
396 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
397 {
398   return new MEDCouplingUMeshCellIterator(this);
399 }
400
401 /*!
402  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
403  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
404  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
405  * Useful for python users.
406  */
407 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
408 {
409   if(!checkConsecutiveCellTypes())
410     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
411   return new MEDCouplingUMeshCellByTypeEntry(this);
412 }
413
414 /*!
415  * Returns a set of all cell types available in \a this mesh.
416  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
417  * \warning this method does not throw any exception even if \a this is not defined.
418  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
419  */
420 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
421 {
422   return _types;
423 }
424
425 /*!
426  * This method returns the sorted list of geometric types in \a this.
427  * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
428  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
429  *
430  * \throw if connectivity in \a this is not correctly defined.
431  *  
432  * \sa MEDCouplingMesh::getAllGeoTypes
433  */
434 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
435 {
436   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
437   checkConnectivityFullyDefined();
438   int nbOfCells(getNumberOfCells());
439   if(nbOfCells==0)
440     return ret;
441   if(getNodalConnectivityArrayLen()<1)
442     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
443   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
444   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
445   for(int i=1;i<nbOfCells;i++,ci++)
446     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
447       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
448   return ret;
449 }
450
451 /*!
452  * This method is a method that compares \a this and \a other.
453  * This method compares \b all attributes, even names and component names.
454  */
455 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
456 {
457   if(!other)
458     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
459   std::ostringstream oss; oss.precision(15);
460   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
461   if(!otherC)
462     {
463       reason="mesh given in input is not castable in MEDCouplingUMesh !";
464       return false;
465     }
466   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
467     return false;
468   if(_mesh_dim!=otherC->_mesh_dim)
469     {
470       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
471       reason=oss.str();
472       return false;
473     }
474   if(_types!=otherC->_types)
475     {
476       oss << "umesh geometric type mismatch :\nThis geometric types are :";
477       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
478         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
479       oss << "\nOther geometric types are :";
480       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
481         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
482       reason=oss.str();
483       return false;
484     }
485   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
486     if(_nodal_connec==0 || otherC->_nodal_connec==0)
487       {
488         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
489         return false;
490       }
491   if(_nodal_connec!=otherC->_nodal_connec)
492     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
493       {
494         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
495         return false;
496       }
497   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
498     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
499       {
500         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
501         return false;
502       }
503   if(_nodal_connec_index!=otherC->_nodal_connec_index)
504     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
505       {
506         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
507         return false;
508       }
509   return true;
510 }
511
512 /*!
513  * Checks if data arrays of this mesh (node coordinates, nodal
514  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
515  * not considered.
516  *  \param [in] other - the mesh to compare with.
517  *  \param [in] prec - precision value used to compare node coordinates.
518  *  \return bool - \a true if the two meshes are same.
519  */
520 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
521 {
522   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
523   if(!otherC)
524     return false;
525   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
526     return false;
527   if(_mesh_dim!=otherC->_mesh_dim)
528     return false;
529   if(_types!=otherC->_types)
530     return false;
531   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
532     if(_nodal_connec==0 || otherC->_nodal_connec==0)
533       return false;
534   if(_nodal_connec!=otherC->_nodal_connec)
535     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
536       return false;
537   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
538     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
539       return false;
540   if(_nodal_connec_index!=otherC->_nodal_connec_index)
541     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
542       return false;
543   return true;
544 }
545
546 /*!
547  * Checks if \a this and \a other meshes are geometrically equivalent with high
548  * probability, else an exception is thrown. The meshes are considered equivalent if
549  * (1) meshes contain the same number of nodes and the same number of elements of the
550  * same types (2) three cells of the two meshes (first, last and middle) are based
551  * on coincident nodes (with a specified precision).
552  *  \param [in] other - the mesh to compare with.
553  *  \param [in] prec - the precision used to compare nodes of the two meshes.
554  *  \throw If the two meshes do not match.
555  */
556 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
557 {
558   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
559   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
560   if(!otherC)
561     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
562 }
563
564 /*!
565  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
566  * cells each node belongs to.
567  * \warning For speed reasons, this method does not check if node ids in the nodal
568  *          connectivity correspond to the size of node coordinates array.
569  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
570  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
571  *        dividing cell ids in \a revNodal into groups each referring to one
572  *        node. Its every element (except the last one) is an index pointing to the
573  *         first id of a group of cells. For example cells sharing the node #1 are 
574  *        described by following range of indices: 
575  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
576  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
577  *        Number of cells sharing the *i*-th node is
578  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
579  * \throw If the coordinates array is not set.
580  * \throw If the nodal connectivity of cells is not defined.
581  * 
582  * \if ENABLE_EXAMPLES
583  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
584  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
585  * \endif
586  */
587 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
588 {
589   checkFullyDefined();
590   int nbOfNodes=getNumberOfNodes();
591   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
592   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
593   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
594   const int *conn=_nodal_connec->getConstPointer();
595   const int *connIndex=_nodal_connec_index->getConstPointer();
596   int nbOfCells=getNumberOfCells();
597   int nbOfEltsInRevNodal=0;
598   for(int eltId=0;eltId<nbOfCells;eltId++)
599     {
600       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
601       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
602       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
603         if(*iter>=0)//for polyhedrons
604           {
605             nbOfEltsInRevNodal++;
606             revNodalIndxPtr[(*iter)+1]++;
607           }
608     }
609   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
610   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
611   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
612   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
613   for(int eltId=0;eltId<nbOfCells;eltId++)
614     {
615       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
616       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
617       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
618         if(*iter>=0)//for polyhedrons
619           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
620     }
621 }
622
623 /// @cond INTERNAL
624
625 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
626 {
627   return id;
628 }
629
630 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
631 {
632   if(!compute)
633     return id+1;
634   else
635     {
636       if(cm.getOrientationStatus(nb,conn1,conn2))
637         return id+1;
638       else
639         return -(id+1);
640     }
641 }
642
643 class MinusOneSonsGenerator
644 {
645 public:
646   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
647   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
648   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
649   static const int DELTA=1;
650 private:
651   const INTERP_KERNEL::CellModel& _cm;
652 };
653
654 class MinusOneSonsGeneratorBiQuadratic
655 {
656 public:
657   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
658   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
659   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
660   static const int DELTA=1;
661 private:
662   const INTERP_KERNEL::CellModel& _cm;
663 };
664
665 class MinusTwoSonsGenerator
666 {
667 public:
668   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
669   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
670   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
671   static const int DELTA=2;
672 private:
673   const INTERP_KERNEL::CellModel& _cm;
674 };
675
676 class MicroEdgesGenerator2D
677 {
678 public:
679   MicroEdgesGenerator2D(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
680   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfMicroEdges(); }
681   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillMicroEdgeNodalConnectivity(sonId,nodalConn,sonNodalConn,typeOfSon); }
682   static const int DELTA=1;
683 private:
684   const INTERP_KERNEL::CellModel& _cm;
685 };
686
687 class MicroEdgesGenerator3D
688 {
689 public:
690   MicroEdgesGenerator3D(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
691   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfMicroEdges(); }
692   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillMicroEdgeNodalConnectivity(sonId,nodalConn,sonNodalConn,typeOfSon); }
693   static const int DELTA=2;
694 private:
695   const INTERP_KERNEL::CellModel& _cm;
696 };
697
698 /// @endcond
699
700 /*!
701  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
702  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
703  * describing correspondence between cells of \a this and the result meshes are
704  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
705  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
706  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
707  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
708  * \warning For speed reasons, this method does not check if node ids in the nodal
709  *          connectivity correspond to the size of node coordinates array.
710  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
711  *          to write this mesh to the MED file, its cells must be sorted using
712  *          sortCellsInMEDFileFrmt().
713  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
714  *         each cell of \a this mesh.
715  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
716  *        dividing cell ids in \a desc into groups each referring to one
717  *        cell of \a this mesh. Its every element (except the last one) is an index
718  *        pointing to the first id of a group of cells. For example cells of the
719  *        result mesh bounding the cell #1 of \a this mesh are described by following
720  *        range of indices:
721  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
722  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
723  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
724  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
725  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
726  *         by each cell of the result mesh.
727  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
728  *        in the result mesh,
729  *        dividing cell ids in \a revDesc into groups each referring to one
730  *        cell of the result mesh the same way as \a descIndx divides \a desc.
731  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
732  *        delete this mesh using decrRef() as it is no more needed.
733  *  \throw If the coordinates array is not set.
734  *  \throw If the nodal connectivity of cells is node defined.
735  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
736  *         revDescIndx == NULL.
737  * 
738  *  \if ENABLE_EXAMPLES
739  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
740  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
741  *  \endif
742  * \sa buildDescendingConnectivity2()
743  */
744 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
745 {
746   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
747 }
748
749 /*!
750  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
751  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
752  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
753  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
754  * \sa MEDCouplingUMesh::buildDescendingConnectivity
755  */
756 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
757 {
758   checkFullyDefined();
759   if(getMeshDimension()!=3)
760     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
761   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
762 }
763
764 /*!
765  * This method computes the micro edges constituting each cell in \a this. Micro edge is an edge for non quadratic cells. Micro edge is an half edge for quadratic cells.
766  * This method works for both meshes with mesh dimenstion equal to 2 or 3. Dynamical cells are not supported (polygons, polyhedrons...)
767  * 
768  * \sa explode3DMeshTo1D, buildDescendingConnectiviy
769  */
770 MEDCouplingUMesh *MEDCouplingUMesh::explodeMeshIntoMicroEdges(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
771 {
772    checkFullyDefined();
773    switch(getMeshDimension())
774      {
775      case 2:
776        return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
777      case 3:
778        return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
779      default:
780        throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explodeMeshIntoMicroEdges : Only 2D and 3D supported !");
781      }
782 }
783
784 /*!
785  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
786  * this->getMeshDimension(), that bound cells of \a this mesh. In
787  * addition arrays describing correspondence between cells of \a this and the result
788  * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
789  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
790  *  mesh. This method differs from buildDescendingConnectivity() in that apart
791  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
792  * result meshes. So a positive id means that order of nodes in corresponding cells
793  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
794  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
795  * i.e. cell ids are one-based.
796  * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
797  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
798  * \warning For speed reasons, this method does not check if node ids in the nodal
799  *          connectivity correspond to the size of node coordinates array.
800  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
801  *          to write this mesh to the MED file, its cells must be sorted using
802  *          sortCellsInMEDFileFrmt().
803  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
804  *         each cell of \a this mesh.
805  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
806  *        dividing cell ids in \a desc into groups each referring to one
807  *        cell of \a this mesh. Its every element (except the last one) is an index
808  *        pointing to the first id of a group of cells. For example cells of the
809  *        result mesh bounding the cell #1 of \a this mesh are described by following
810  *        range of indices:
811  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
812  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
813  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
814  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
815  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
816  *         by each cell of the result mesh.
817  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
818  *        in the result mesh,
819  *        dividing cell ids in \a revDesc into groups each referring to one
820  *        cell of the result mesh the same way as \a descIndx divides \a desc.
821  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
822  *        shares the node coordinates array with \a this mesh. The caller is to
823  *        delete this mesh using decrRef() as it is no more needed.
824  *  \throw If the coordinates array is not set.
825  *  \throw If the nodal connectivity of cells is node defined.
826  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
827  *         revDescIndx == NULL.
828  * 
829  *  \if ENABLE_EXAMPLES
830  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
831  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
832  *  \endif
833  * \sa buildDescendingConnectivity()
834  */
835 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
836 {
837   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
838 }
839
840 /*!
841  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
842  * For speed reasons no check of this will be done. This method calls
843  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
844  * This method lists cell by cell in \b this which are its neighbors. To compute the result
845  * only connectivities are considered.
846  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
847  * The format of return is hence \ref numbering-indirect.
848  *
849  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
850  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
851  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
852  * is equal to the last values in \b neighborsIndx.
853  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
854  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
855  */
856 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
857 {
858   MCAuto<DataArrayInt> desc=DataArrayInt::New();
859   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
860   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
861   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
862   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
863   meshDM1=0;
864   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
865 }
866
867 void MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne(const DataArrayInt *nodeNeigh, const DataArrayInt *nodeNeighI, MCAuto<DataArrayInt>& cellNeigh, MCAuto<DataArrayInt>& cellNeighIndex) const
868 {
869   if(!nodeNeigh || !nodeNeighI)
870     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : null pointer !");
871   checkConsistencyLight();
872   nodeNeigh->checkAllocated(); nodeNeighI->checkAllocated();
873   nodeNeigh->checkNbOfComps(1,"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : node neigh");
874   nodeNeighI->checkNbOfComps(1,"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : node neigh index");
875   nodeNeighI->checkNbOfTuples(1+getNumberOfNodes(),"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : invalid length");
876   int nbCells(getNumberOfCells());
877   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin()),*ne(nodeNeigh->begin()),*nei(nodeNeighI->begin());
878   cellNeigh=DataArrayInt::New(); cellNeigh->alloc(0,1); cellNeighIndex=DataArrayInt::New(); cellNeighIndex->alloc(1,1); cellNeighIndex->setIJ(0,0,0);
879   for(int i=0;i<nbCells;i++)
880     {
881       std::set<int> s;
882       for(const int *it=c+ci[i]+1;it!=c+ci[i+1];it++)
883         if(*it>=0)
884           s.insert(ne+nei[*it],ne+nei[*it+1]);
885       s.erase(i);
886       cellNeigh->insertAtTheEnd(s.begin(),s.end());
887       cellNeighIndex->pushBackSilent(cellNeigh->getNumberOfTuples());
888     }
889 }
890
891 /*!
892  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
893  * of MEDCouplingUMesh::computeNeighborsOfCells.
894  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
895  * typically the case to extract a set a neighbours,
896  * excluding a set of meshdim-1 cells in input descending connectivity.
897  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
898  * the result of MEDCouplingUMesh::buildDescendingConnectivity.
899  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
900  * are considered.
901  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
902  *
903  * \param [in] desc descending connectivity array.
904  * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
905  * \param [in] revDesc reverse descending connectivity array.
906  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
907  * \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
908  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
909  * \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.
910  */
911 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
912                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
913 {
914   if(!desc || !descIndx || !revDesc || !revDescIndx)
915     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
916   const int *descPtr=desc->getConstPointer();
917   const int *descIPtr=descIndx->getConstPointer();
918   const int *revDescPtr=revDesc->getConstPointer();
919   const int *revDescIPtr=revDescIndx->getConstPointer();
920   //
921   int nbCells=descIndx->getNumberOfTuples()-1;
922   MCAuto<DataArrayInt> out0=DataArrayInt::New();
923   MCAuto<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
924   int *out1Ptr=out1->getPointer();
925   *out1Ptr++=0;
926   out0->reserve(desc->getNumberOfTuples());
927   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
928     {
929       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
930         {
931           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
932           s.erase(i);
933           out0->insertAtTheEnd(s.begin(),s.end());
934         }
935       *out1Ptr=out0->getNumberOfTuples();
936     }
937   neighbors=out0.retn();
938   neighborsIndx=out1.retn();
939 }
940
941 /*!
942  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
943  * For speed reasons no check of this will be done. This method calls
944  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
945  * This method lists node by node in \b this which are its neighbors. To compute the result
946  * only connectivities are considered.
947  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
948  *
949  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
950  * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
951  * parameter allows to select the right part in this array (\ref numbering-indirect).
952  * The number of tuples is equal to the last values in \b neighborsIndx.
953  * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
954  * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
955  */
956 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
957 {
958   checkFullyDefined();
959   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
960   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
961   MCAuto<MEDCouplingUMesh> mesh1D;
962   switch(mdim)
963   {
964     case 3:
965       {
966         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
967         break;
968       }
969     case 2:
970       {
971         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
972         break;
973       }
974     case 1:
975       {
976         mesh1D=const_cast<MEDCouplingUMesh *>(this);
977         mesh1D->incrRef();
978         break;
979       }
980     default:
981       {
982         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
983       }
984   }
985   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
986   mesh1D->getReverseNodalConnectivity(desc,descIndx);
987   MCAuto<DataArrayInt> ret0(DataArrayInt::New());
988   ret0->alloc(desc->getNumberOfTuples(),1);
989   int *r0Pt(ret0->getPointer());
990   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
991   for(int i=0;i<nbNodes;i++,rni++)
992     {
993       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
994         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
995     }
996   neighbors=ret0.retn();
997   neighborsIdx=descIndx.retn();
998 }
999
1000 /// @cond INTERNAL
1001
1002 /*!
1003  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
1004  * For speed reasons no check of this will be done.
1005  */
1006 template<class SonsGenerator>
1007 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
1008 {
1009   if(!desc || !descIndx || !revDesc || !revDescIndx)
1010     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
1011   checkConnectivityFullyDefined();
1012   int nbOfCells=getNumberOfCells();
1013   int nbOfNodes=getNumberOfNodes();
1014   MCAuto<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
1015   int *revNodalIndxPtr=revNodalIndx->getPointer();
1016   const int *conn=_nodal_connec->getConstPointer();
1017   const int *connIndex=_nodal_connec_index->getConstPointer();
1018   std::string name="Mesh constituent of "; name+=getName();
1019   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
1020   ret->setCoords(getCoords());
1021   ret->allocateCells(2*nbOfCells);
1022   descIndx->alloc(nbOfCells+1,1);
1023   MCAuto<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
1024   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
1025   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
1026     {
1027       int pos=connIndex[eltId];
1028       int posP1=connIndex[eltId+1];
1029       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
1030       SonsGenerator sg(cm);
1031       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
1032       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
1033       for(unsigned i=0;i<nbOfSons;i++)
1034         {
1035           INTERP_KERNEL::NormalizedCellType cmsId;
1036           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
1037           for(unsigned k=0;k<nbOfNodesSon;k++)
1038             if(tmp[k]>=0)
1039               revNodalIndxPtr[tmp[k]+1]++;
1040           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
1041           revDesc2->pushBackSilent(eltId);
1042         }
1043       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
1044     }
1045   int nbOfCellsM1=ret->getNumberOfCells();
1046   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
1047   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
1048   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
1049   int *revNodalPtr=revNodal->getPointer();
1050   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
1051   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
1052   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
1053     {
1054       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
1055       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
1056       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
1057         if(*iter>=0)//for polyhedrons
1058           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
1059     }
1060   //
1061   DataArrayInt *commonCells=0,*commonCellsI=0;
1062   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
1063   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1064   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1065   int newNbOfCellsM1=-1;
1066   MCAuto<DataArrayInt> o2nM1=DataArrayInt::ConvertIndexArrayToO2N(nbOfCellsM1,commonCells->begin(),
1067                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1068   std::vector<bool> isImpacted(nbOfCellsM1,false);
1069   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1070     for(int work2=work[0];work2!=work[1];work2++)
1071       isImpacted[commonCellsPtr[work2]]=true;
1072   const int *o2nM1Ptr=o2nM1->getConstPointer();
1073   MCAuto<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1074   const int *n2oM1Ptr=n2oM1->getConstPointer();
1075   MCAuto<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1076   ret2->copyTinyInfoFrom(this);
1077   desc->alloc(descIndx->back(),1);
1078   int *descPtr=desc->getPointer();
1079   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1080   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1081     {
1082       if(!isImpacted[i])
1083         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1084       else
1085         {
1086           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1087             {
1088               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1089               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1090             }
1091           else
1092             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1093         }
1094     }
1095   revDesc->reserve(newNbOfCellsM1);
1096   revDescIndx->alloc(newNbOfCellsM1+1,1);
1097   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1098   const int *revDesc2Ptr=revDesc2->getConstPointer();
1099   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1100     {
1101       int oldCellIdM1=n2oM1Ptr[i];
1102       if(!isImpacted[oldCellIdM1])
1103         {
1104           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1105           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1106         }
1107       else
1108         {
1109           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1110             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1111           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1112           commonCellsIPtr++;
1113         }
1114     }
1115   //
1116   return ret2.retn();
1117 }
1118
1119 struct MEDCouplingAccVisit
1120 {
1121   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1122   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1123   int _new_nb_of_nodes;
1124 };
1125
1126 /// @endcond
1127
1128 /*!
1129  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1130  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1131  * array of cell ids. Pay attention that after conversion all algorithms work slower
1132  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1133  * conversion due presence of invalid ids in the array of cells to convert, as a
1134  * result \a this mesh contains some already converted elements. In this case the 2D
1135  * mesh remains valid but 3D mesh becomes \b inconsistent!
1136  *  \warning This method can significantly modify the order of geometric types in \a this,
1137  *          hence, to write this mesh to the MED file, its cells must be sorted using
1138  *          sortCellsInMEDFileFrmt().
1139  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1140  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1141  *         cellIdsToConvertBg.
1142  *  \throw If the coordinates array is not set.
1143  *  \throw If the nodal connectivity of cells is node defined.
1144  *  \throw If dimension of \a this mesh is not either 2 or 3.
1145  *
1146  *  \if ENABLE_EXAMPLES
1147  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1148  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1149  *  \endif
1150  */
1151 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1152 {
1153   checkFullyDefined();
1154   int dim=getMeshDimension();
1155   if(dim<2 || dim>3)
1156     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1157   int nbOfCells(getNumberOfCells());
1158   if(dim==2)
1159     {
1160       const int *connIndex=_nodal_connec_index->getConstPointer();
1161       int *conn=_nodal_connec->getPointer();
1162       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1163         {
1164           if(*iter>=0 && *iter<nbOfCells)
1165             {
1166               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1167               if(!cm.isQuadratic())
1168                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1169               else
1170                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1171             }
1172           else
1173             {
1174               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1175               oss << " in range [0," << nbOfCells << ") !";
1176               throw INTERP_KERNEL::Exception(oss.str());
1177             }
1178         }
1179     }
1180   else
1181     {
1182       int *connIndex(_nodal_connec_index->getPointer());
1183       const int *connOld(_nodal_connec->getConstPointer());
1184       MCAuto<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1185       std::vector<bool> toBeDone(nbOfCells,false);
1186       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1187         {
1188           if(*iter>=0 && *iter<nbOfCells)
1189             toBeDone[*iter]=true;
1190           else
1191             {
1192               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1193               oss << " in range [0," << nbOfCells << ") !";
1194               throw INTERP_KERNEL::Exception(oss.str());
1195             }
1196         }
1197       for(int cellId=0;cellId<nbOfCells;cellId++)
1198         {
1199           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1200           int lgthOld(posP1-pos-1);
1201           if(toBeDone[cellId])
1202             {
1203               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1204               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1205               int *tmp(new int[nbOfFaces*lgthOld+1]);
1206               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1207               for(unsigned j=0;j<nbOfFaces;j++)
1208                 {
1209                   INTERP_KERNEL::NormalizedCellType type;
1210                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1211                   work+=offset;
1212                   *work++=-1;
1213                 }
1214               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1215               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1216               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1217               delete [] tmp;
1218             }
1219           else
1220             {
1221               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1222               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1223             }
1224         }
1225       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1226     }
1227   computeTypes();
1228 }
1229
1230 /*!
1231  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1232  * polyhedrons (if \a this is a 3D mesh).
1233  *  \warning As this method is purely for user-friendliness and no optimization is
1234  *          done to avoid construction of a useless vector, this method can be costly
1235  *          in memory.
1236  *  \throw If the coordinates array is not set.
1237  *  \throw If the nodal connectivity of cells is node defined.
1238  *  \throw If dimension of \a this mesh is not either 2 or 3.
1239  */
1240 void MEDCouplingUMesh::convertAllToPoly()
1241 {
1242   int nbOfCells=getNumberOfCells();
1243   std::vector<int> cellIds(nbOfCells);
1244   for(int i=0;i<nbOfCells;i++)
1245     cellIds[i]=i;
1246   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1247 }
1248
1249 /*!
1250  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1251  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1252  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1253  * base facet of the volume and the second half of nodes describes an opposite facet
1254  * having the same number of nodes as the base one. This method converts such
1255  * connectivity to a valid polyhedral format where connectivity of each facet is
1256  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1257  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1258  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1259  * a correct orientation of the first facet of a polyhedron, else orientation of a
1260  * corrected cell is reverse.<br>
1261  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1262  * it releases the user from boring description of polyhedra connectivity in the valid
1263  * format.
1264  *  \throw If \a this->getMeshDimension() != 3.
1265  *  \throw If \a this->getSpaceDimension() != 3.
1266  *  \throw If the nodal connectivity of cells is not defined.
1267  *  \throw If the coordinates array is not set.
1268  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1269  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1270  *
1271  *  \if ENABLE_EXAMPLES
1272  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1273  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1274  *  \endif
1275  */
1276 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1277 {
1278   checkFullyDefined();
1279   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1280     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1281   int nbOfCells=getNumberOfCells();
1282   MCAuto<DataArrayInt> newCi=DataArrayInt::New();
1283   newCi->alloc(nbOfCells+1,1);
1284   int *newci=newCi->getPointer();
1285   const int *ci=_nodal_connec_index->getConstPointer();
1286   const int *c=_nodal_connec->getConstPointer();
1287   newci[0]=0;
1288   for(int i=0;i<nbOfCells;i++)
1289     {
1290       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1291       if(type==INTERP_KERNEL::NORM_POLYHED)
1292         {
1293           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1294             {
1295               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1296               throw INTERP_KERNEL::Exception(oss.str());
1297             }
1298           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1299           if(n2%2!=0)
1300             {
1301               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 !";
1302               throw INTERP_KERNEL::Exception(oss.str());
1303             }
1304           int n1=(int)(n2/2);
1305           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)
1306         }
1307       else
1308         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1309     }
1310   MCAuto<DataArrayInt> newC=DataArrayInt::New();
1311   newC->alloc(newci[nbOfCells],1);
1312   int *newc=newC->getPointer();
1313   for(int i=0;i<nbOfCells;i++)
1314     {
1315       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1316       if(type==INTERP_KERNEL::NORM_POLYHED)
1317         {
1318           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1319           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1320           *newc++=-1;
1321           for(std::size_t j=0;j<n1;j++)
1322             {
1323               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1324               newc[n1+5*j]=-1;
1325               newc[n1+5*j+1]=c[ci[i]+1+j];
1326               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1327               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1328               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1329             }
1330           newc+=n1*6;
1331         }
1332       else
1333         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1334     }
1335   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1336   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1337 }
1338
1339
1340 /*!
1341  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1342  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1343  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1344  *          to write this mesh to the MED file, its cells must be sorted using
1345  *          sortCellsInMEDFileFrmt().
1346  * \warning Cells (and most notably polyhedrons) must be correctly oriented for this to work
1347  *          properly. See orientCorrectlyPolyhedrons() and arePolyhedronsNotCorrectlyOriented().
1348  * \return \c true if at least one cell has been converted, \c false else. In the
1349  *         last case the nodal connectivity remains unchanged.
1350  * \throw If the coordinates array is not set.
1351  * \throw If the nodal connectivity of cells is not defined.
1352  * \throw If \a this->getMeshDimension() < 0.
1353  */
1354 bool MEDCouplingUMesh::unPolyze()
1355 {
1356   checkFullyDefined();
1357   int mdim=getMeshDimension();
1358   if(mdim<0)
1359     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1360   if(mdim<=1)
1361     return false;
1362   int nbOfCells=getNumberOfCells();
1363   if(nbOfCells<1)
1364     return false;
1365   int initMeshLgth=getNodalConnectivityArrayLen();
1366   int *conn=_nodal_connec->getPointer();
1367   int *index=_nodal_connec_index->getPointer();
1368   int posOfCurCell=0;
1369   int newPos=0;
1370   int lgthOfCurCell;
1371   bool ret=false;
1372   for(int i=0;i<nbOfCells;i++)
1373     {
1374       lgthOfCurCell=index[i+1]-posOfCurCell;
1375       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1376       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1377       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1378       int newLgth;
1379       if(cm.isDynamic())
1380         {
1381           switch(cm.getDimension())
1382           {
1383             case 2:
1384               {
1385                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1386                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1387                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1388                 break;
1389               }
1390             case 3:
1391               {
1392                 int nbOfFaces,lgthOfPolyhConn;
1393                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1394                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1395                 break;
1396               }
1397             case 1:
1398               {
1399                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1400                 break;
1401               }
1402           }
1403           ret=ret || (newType!=type);
1404           conn[newPos]=newType;
1405           newPos+=newLgth+1;
1406           posOfCurCell=index[i+1];
1407           index[i+1]=newPos;
1408         }
1409       else
1410         {
1411           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1412           newPos+=lgthOfCurCell;
1413           posOfCurCell+=lgthOfCurCell;
1414           index[i+1]=newPos;
1415         }
1416     }
1417   if(newPos!=initMeshLgth)
1418     _nodal_connec->reAlloc(newPos);
1419   if(ret)
1420     computeTypes();
1421   return ret;
1422 }
1423
1424 /*!
1425  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1426  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1427  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1428  *
1429  * \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 
1430  *             precision.
1431  */
1432 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1433 {
1434   checkFullyDefined();
1435   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1436     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1437   MCAuto<DataArrayDouble> coords=getCoords()->deepCopy();
1438   coords->recenterForMaxPrecision(eps);
1439   //
1440   int nbOfCells=getNumberOfCells();
1441   const int *conn=_nodal_connec->getConstPointer();
1442   const int *index=_nodal_connec_index->getConstPointer();
1443   MCAuto<DataArrayInt> connINew=DataArrayInt::New();
1444   connINew->alloc(nbOfCells+1,1);
1445   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1446   MCAuto<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1447   bool changed=false;
1448   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1449     {
1450       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1451         {
1452           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1453           changed=true;
1454         }
1455       else
1456         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1457       *connINewPtr=connNew->getNumberOfTuples();
1458     }
1459   if(changed)
1460     setConnectivity(connNew,connINew,false);
1461 }
1462
1463 /*!
1464  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1465  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1466  * the format of the returned DataArrayInt instance.
1467  * 
1468  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1469  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1470  */
1471 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1472 {
1473   checkConnectivityFullyDefined();
1474   const int *maxEltPt(std::max_element(_nodal_connec->begin(),_nodal_connec->end()));
1475   int maxElt(maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1);
1476   std::vector<bool> retS(maxElt,false);
1477   computeNodeIdsAlg(retS);
1478   return DataArrayInt::BuildListOfSwitchedOn(retS);
1479 }
1480
1481 /*!
1482  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1483  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1484  */
1485 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1486 {
1487   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1488   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1489   for(int i=0;i<nbOfCells;i++)
1490     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1491       if(conn[j]>=0)
1492         {
1493           if(conn[j]<nbOfNodes)
1494             nodeIdsInUse[conn[j]]=true;
1495           else
1496             {
1497               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1498               throw INTERP_KERNEL::Exception(oss.str());
1499             }
1500         }
1501 }
1502
1503 /*!
1504  * Finds nodes not used in any cell and returns an array giving a new id to every node
1505  * by excluding the unused nodes, for which the array holds -1. The result array is
1506  * a mapping in "Old to New" mode. 
1507  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1508  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1509  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1510  *          if the node is unused or a new id else. The caller is to delete this
1511  *          array using decrRef() as it is no more needed.  
1512  *  \throw If the coordinates array is not set.
1513  *  \throw If the nodal connectivity of cells is not defined.
1514  *  \throw If the nodal connectivity includes an invalid id.
1515  *
1516  *  \if ENABLE_EXAMPLES
1517  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1518  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1519  *  \endif
1520  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1521  */
1522 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1523 {
1524   nbrOfNodesInUse=-1;
1525   int nbOfNodes(getNumberOfNodes());
1526   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1527   ret->alloc(nbOfNodes,1);
1528   int *traducer=ret->getPointer();
1529   std::fill(traducer,traducer+nbOfNodes,-1);
1530   int nbOfCells=getNumberOfCells();
1531   const int *connIndex=_nodal_connec_index->getConstPointer();
1532   const int *conn=_nodal_connec->getConstPointer();
1533   for(int i=0;i<nbOfCells;i++)
1534     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1535       if(conn[j]>=0)
1536         {
1537           if(conn[j]<nbOfNodes)
1538             traducer[conn[j]]=1;
1539           else
1540             {
1541               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1542               throw INTERP_KERNEL::Exception(oss.str());
1543             }
1544         }
1545   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1546   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1547   return ret.retn();
1548 }
1549
1550 /*!
1551  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1552  * For each cell in \b this the number of nodes constituting cell is computed.
1553  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1554  * So for pohyhedrons some nodes can be counted several times in the returned result.
1555  * 
1556  * \return a newly allocated array
1557  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1558  */
1559 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1560 {
1561   checkConnectivityFullyDefined();
1562   int nbOfCells=getNumberOfCells();
1563   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1564   ret->alloc(nbOfCells,1);
1565   int *retPtr=ret->getPointer();
1566   const int *conn=getNodalConnectivity()->getConstPointer();
1567   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1568   for(int i=0;i<nbOfCells;i++,retPtr++)
1569     {
1570       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1571         *retPtr=connI[i+1]-connI[i]-1;
1572       else
1573         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1574     }
1575   return ret.retn();
1576 }
1577
1578 /*!
1579  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1580  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1581  *
1582  * \return DataArrayInt * - new object to be deallocated by the caller.
1583  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1584  */
1585 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1586 {
1587   checkConnectivityFullyDefined();
1588   int nbOfCells=getNumberOfCells();
1589   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1590   ret->alloc(nbOfCells,1);
1591   int *retPtr=ret->getPointer();
1592   const int *conn=getNodalConnectivity()->getConstPointer();
1593   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1594   for(int i=0;i<nbOfCells;i++,retPtr++)
1595     {
1596       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1597       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1598         *retPtr=(int)s.size();
1599       else
1600         {
1601           s.erase(-1);
1602           *retPtr=(int)s.size();
1603         }
1604     }
1605   return ret.retn();
1606 }
1607
1608 /*!
1609  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1610  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1611  * 
1612  * \return a newly allocated array
1613  */
1614 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1615 {
1616   checkConnectivityFullyDefined();
1617   int nbOfCells=getNumberOfCells();
1618   MCAuto<DataArrayInt> ret=DataArrayInt::New();
1619   ret->alloc(nbOfCells,1);
1620   int *retPtr=ret->getPointer();
1621   const int *conn=getNodalConnectivity()->getConstPointer();
1622   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1623   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1624     {
1625       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1626       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1627     }
1628   return ret.retn();
1629 }
1630
1631 /*!
1632  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1633  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1634  * array mean that the corresponding old node is no more used. 
1635  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1636  *           this->getNumberOfNodes() before call of this method. The caller is to
1637  *           delete this array using decrRef() as it is no more needed. 
1638  *  \throw If the coordinates array is not set.
1639  *  \throw If the nodal connectivity of cells is not defined.
1640  *  \throw If the nodal connectivity includes an invalid id.
1641  *  \sa areAllNodesFetched
1642  *
1643  *  \if ENABLE_EXAMPLES
1644  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1645  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1646  *  \endif
1647  */
1648 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1649 {
1650   return MEDCouplingPointSet::zipCoordsTraducer();
1651 }
1652
1653 /*!
1654  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1655  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1656  */
1657 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1658 {
1659   switch(compType)
1660   {
1661     case 0:
1662       return AreCellsEqualPolicy0(conn,connI,cell1,cell2);
1663     case 1:
1664       return AreCellsEqualPolicy1(conn,connI,cell1,cell2);
1665     case 2:
1666       return AreCellsEqualPolicy2(conn,connI,cell1,cell2);
1667     case 3:
1668       return AreCellsEqualPolicy2NoType(conn,connI,cell1,cell2);
1669     case 7:
1670       return AreCellsEqualPolicy7(conn,connI,cell1,cell2);
1671   }
1672   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1673 }
1674
1675 /*!
1676  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1677  */
1678 int MEDCouplingUMesh::AreCellsEqualPolicy0(const int *conn, const int *connI, int cell1, int cell2)
1679 {
1680   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1681     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1682   return 0;
1683 }
1684
1685 /*!
1686  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1687  */
1688 int MEDCouplingUMesh::AreCellsEqualPolicy1(const int *conn, const int *connI, int cell1, int cell2)
1689 {
1690   int sz=connI[cell1+1]-connI[cell1];
1691   if(sz==connI[cell2+1]-connI[cell2])
1692     {
1693       if(conn[connI[cell1]]==conn[connI[cell2]])
1694         {
1695           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1696           unsigned dim=cm.getDimension();
1697           if(dim!=3)
1698             {
1699               if(dim!=1)
1700                 {
1701                   int sz1=2*(sz-1);
1702                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1703                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1704                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1705                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1706                   return work!=tmp+sz1?1:0;
1707                 }
1708               else
1709                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1710             }
1711           else
1712             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy1 : not implemented yet for meshdim == 3 !");
1713         }
1714     }
1715   return 0;
1716 }
1717
1718 /*!
1719  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1720  */
1721 int MEDCouplingUMesh::AreCellsEqualPolicy2(const int *conn, const int *connI, int cell1, int cell2)
1722 {
1723   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1724     {
1725       if(conn[connI[cell1]]==conn[connI[cell2]])
1726         {
1727           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1728           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1729           return s1==s2?1:0;
1730         }
1731     }
1732   return 0;
1733 }
1734
1735 /*!
1736  * This method is less restrictive than AreCellsEqualPolicy2. Here the geometric type is absolutely not taken into account !
1737  */
1738 int MEDCouplingUMesh::AreCellsEqualPolicy2NoType(const int *conn, const int *connI, int cell1, int cell2)
1739 {
1740   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1741     {
1742       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1743       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1744       return s1==s2?1:0;
1745     }
1746   return 0;
1747 }
1748
1749 /*!
1750  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1751  */
1752 int MEDCouplingUMesh::AreCellsEqualPolicy7(const int *conn, const int *connI, int cell1, int cell2)
1753 {
1754   int sz=connI[cell1+1]-connI[cell1];
1755   if(sz==connI[cell2+1]-connI[cell2])
1756     {
1757       if(conn[connI[cell1]]==conn[connI[cell2]])
1758         {
1759           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1760           unsigned dim=cm.getDimension();
1761           if(dim!=3)
1762             {
1763               if(dim!=1)
1764                 {
1765                   int sz1=2*(sz-1);
1766                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1767                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1768                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1769                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1770                   if(work!=tmp+sz1)
1771                     return 1;
1772                   else
1773                     {
1774                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1775                       std::reverse_iterator<int *> it2((int *)tmp);
1776                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1777                         return 2;
1778                       else
1779                         return 0;
1780                     }
1781
1782                   return work!=tmp+sz1?1:0;
1783                 }
1784               else
1785                 {//case of SEG2 and SEG3
1786                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1787                     return 1;
1788                   if(!cm.isQuadratic())
1789                     {
1790                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1791                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1792                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1793                         return 2;
1794                       return 0;
1795                     }
1796                   else
1797                     {
1798                       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])
1799                         return 2;
1800                       return 0;
1801                     }
1802                 }
1803             }
1804           else
1805             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy7 : not implemented yet for meshdim == 3 !");
1806         }
1807     }
1808   return 0;
1809 }
1810
1811 /*!
1812  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1813  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1814  * and result remains unchanged.
1815  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1816  * If in 'candidates' pool -1 value is considered as an empty value.
1817  * WARNING this method returns only ONE set of result !
1818  */
1819 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1820 {
1821   if(candidates.size()<1)
1822     return false;
1823   bool ret=false;
1824   std::vector<int>::const_iterator iter=candidates.begin();
1825   int start=(*iter++);
1826   for(;iter!=candidates.end();iter++)
1827     {
1828       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1829       if(status!=0)
1830         {
1831           if(!ret)
1832             {
1833               result->pushBackSilent(start);
1834               ret=true;
1835             }
1836           if(status==1)
1837             result->pushBackSilent(*iter);
1838           else
1839             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1840         }
1841     }
1842   return ret;
1843 }
1844
1845 /*!
1846  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1847  * by \a compType.
1848  * This method keeps the coordiantes of \a this. This method is time consuming.
1849  *
1850  * \param [in] compType input specifying the technique used to compare cells each other.
1851  *   - 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.
1852  *   - 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)
1853  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1854  *   - 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
1855  * can be used for users not sensitive to orientation of cell
1856  * \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.
1857  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1858  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1859  * \return the correspondance array old to new in a newly allocated array.
1860  * 
1861  */
1862 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1863 {
1864   MCAuto<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1865   getReverseNodalConnectivity(revNodal,revNodalI);
1866   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1867 }
1868
1869 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1870                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1871 {
1872   MCAuto<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1873   int nbOfCells=nodalI->getNumberOfTuples()-1;
1874   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1875   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1876   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1877   std::vector<bool> isFetched(nbOfCells,false);
1878   if(startCellId==0)
1879     {
1880       for(int i=0;i<nbOfCells;i++)
1881         {
1882           if(!isFetched[i])
1883             {
1884               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1885               std::vector<int> v,v2;
1886               if(connOfNode!=connPtr+connIPtr[i+1])
1887                 {
1888                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1889                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1890                   connOfNode++;
1891                 }
1892               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1893                 if(*connOfNode>=0)
1894                   {
1895                     v=v2;
1896                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1897                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1898                     v2.resize(std::distance(v2.begin(),it));
1899                   }
1900               if(v2.size()>1)
1901                 {
1902                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1903                     {
1904                       int pos=commonCellsI->back();
1905                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1906                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1907                         isFetched[*it]=true;
1908                     }
1909                 }
1910             }
1911         }
1912     }
1913   else
1914     {
1915       for(int i=startCellId;i<nbOfCells;i++)
1916         {
1917           if(!isFetched[i])
1918             {
1919               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1920               std::vector<int> v,v2;
1921               if(connOfNode!=connPtr+connIPtr[i+1])
1922                 {
1923                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1924                   connOfNode++;
1925                 }
1926               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1927                 if(*connOfNode>=0)
1928                   {
1929                     v=v2;
1930                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1931                     v2.resize(std::distance(v2.begin(),it));
1932                   }
1933               if(v2.size()>1)
1934                 {
1935                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1936                     {
1937                       int pos=commonCellsI->back();
1938                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1939                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1940                         isFetched[*it]=true;
1941                     }
1942                 }
1943             }
1944         }
1945     }
1946   commonCellsArr=commonCells.retn();
1947   commonCellsIArr=commonCellsI.retn();
1948 }
1949
1950 /*!
1951  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1952  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1953  * than \a this->getNumberOfCells() in the returned array means that there is no
1954  * corresponding cell in \a this mesh.
1955  * It is expected that \a this and \a other meshes share the same node coordinates
1956  * array, if it is not so an exception is thrown. 
1957  *  \param [in] other - the mesh to compare with.
1958  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1959  *         valid values [0,1,2], see zipConnectivityTraducer().
1960  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1961  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1962  *         values. The caller is to delete this array using
1963  *         decrRef() as it is no more needed.
1964  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1965  *         mesh.
1966  *
1967  *  \if ENABLE_EXAMPLES
1968  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1969  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1970  *  \endif
1971  *  \sa checkDeepEquivalOnSameNodesWith()
1972  *  \sa checkGeoEquivalWith()
1973  */
1974 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1975 {
1976   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1977   int nbOfCells=getNumberOfCells();
1978   static const int possibleCompType[]={0,1,2};
1979   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1980     {
1981       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1982       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1983       oss << " !";
1984       throw INTERP_KERNEL::Exception(oss.str());
1985     }
1986   MCAuto<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1987   arr=o2n->subArray(nbOfCells);
1988   arr->setName(other->getName());
1989   int tmp;
1990   if(other->getNumberOfCells()==0)
1991     return true;
1992   return arr->getMaxValue(tmp)<nbOfCells;
1993 }
1994
1995 /*!
1996  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1997  * This method tries to determine if \b other is fully included in \b this.
1998  * The main difference is that this method is not expected to throw exception.
1999  * This method has two outputs :
2000  *
2001  * \param other other mesh
2002  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
2003  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
2004  */
2005 bool MEDCouplingUMesh::areCellsIncludedInPolicy7(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
2006 {
2007   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
2008   DataArrayInt *commonCells=0,*commonCellsI=0;
2009   int thisNbCells=getNumberOfCells();
2010   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
2011   MCAuto<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
2012   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
2013   int otherNbCells=other->getNumberOfCells();
2014   MCAuto<DataArrayInt> arr2=DataArrayInt::New();
2015   arr2->alloc(otherNbCells,1);
2016   arr2->fillWithZero();
2017   int *arr2Ptr=arr2->getPointer();
2018   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
2019   for(int i=0;i<nbOfCommon;i++)
2020     {
2021       int start=commonCellsPtr[commonCellsIPtr[i]];
2022       if(start<thisNbCells)
2023         {
2024           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
2025             {
2026               int sig=commonCellsPtr[j]>0?1:-1;
2027               int val=std::abs(commonCellsPtr[j])-1;
2028               if(val>=thisNbCells)
2029                 arr2Ptr[val-thisNbCells]=sig*(start+1);
2030             }
2031         }
2032     }
2033   arr2->setName(other->getName());
2034   if(arr2->presenceOfValue(0))
2035     return false;
2036   arr=arr2.retn();
2037   return true;
2038 }
2039
2040 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
2041 {
2042   if(!other)
2043     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
2044   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
2045   if(!otherC)
2046     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
2047   std::vector<const MEDCouplingUMesh *> ms(2);
2048   ms[0]=this;
2049   ms[1]=otherC;
2050   return MergeUMeshesOnSameCoords(ms);
2051 }
2052
2053 /*!
2054  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2055  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2056  * cellIds is not given explicitely but by a range python like.
2057  * 
2058  * \param start
2059  * \param end
2060  * \param step
2061  * \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.
2062  * \return a newly allocated
2063  * 
2064  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2065  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2066  */
2067 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(int start, int end, int step, bool keepCoords) const
2068 {
2069   if(getMeshDimension()!=-1)
2070     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelfSlice(start,end,step,keepCoords));
2071   else
2072     {
2073       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfSlice for -1 dimension mesh ");
2074       if(newNbOfCells!=1)
2075         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2076       if(start!=0)
2077         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2078       incrRef();
2079       return const_cast<MEDCouplingUMesh *>(this);
2080     }
2081 }
2082
2083 /*!
2084  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2085  * The result mesh shares or not the node coordinates array with \a this mesh depending
2086  * on \a keepCoords parameter.
2087  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2088  *           to write this mesh to the MED file, its cells must be sorted using
2089  *           sortCellsInMEDFileFrmt().
2090  *  \param [in] begin - an array of cell ids to include to the new mesh.
2091  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2092  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2093  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2094  *         by calling zipCoords().
2095  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2096  *         to delete this mesh using decrRef() as it is no more needed. 
2097  *  \throw If the coordinates array is not set.
2098  *  \throw If the nodal connectivity of cells is not defined.
2099  *  \throw If any cell id in the array \a begin is not valid.
2100  *
2101  *  \if ENABLE_EXAMPLES
2102  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2103  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2104  *  \endif
2105  */
2106 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2107 {
2108   if(getMeshDimension()!=-1)
2109     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
2110   else
2111     {
2112       if(end-begin!=1)
2113         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2114       if(begin[0]!=0)
2115         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2116       incrRef();
2117       return const_cast<MEDCouplingUMesh *>(this);
2118     }
2119 }
2120
2121 /*!
2122  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2123  *
2124  * 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.
2125  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2126  * The number of cells of \b this will remain the same with this method.
2127  *
2128  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
2129  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
2130  * \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 ).
2131  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2132  */
2133 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2134 {
2135   checkConnectivityFullyDefined();
2136   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2137   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2138     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2139   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2140     {
2141       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : 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());
2144     }
2145   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2146   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2147     {
2148       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2149       throw INTERP_KERNEL::Exception(oss.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   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2156     {
2157       if(*it>=0 && *it<nbOfCells)
2158         {
2159           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2160         }
2161       else
2162         {
2163           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2164           throw INTERP_KERNEL::Exception(oss.str());
2165         }
2166     }
2167   if(easyAssign)
2168     {
2169       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2170       computeTypes();
2171     }
2172   else
2173     {
2174       DataArrayInt *arrOut=0,*arrIOut=0;
2175       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2176                                                arrOut,arrIOut);
2177       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2178       setConnectivity(arrOut,arrIOut,true);
2179     }
2180 }
2181
2182 void MEDCouplingUMesh::setPartOfMySelfSlice(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2183 {
2184   checkConnectivityFullyDefined();
2185   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2186   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2187     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelfSlice : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2188   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2189     {
2190       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2191       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2192       throw INTERP_KERNEL::Exception(oss.str());
2193     }
2194   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelfSlice : ");
2195   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2196     {
2197       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2198       throw INTERP_KERNEL::Exception(oss.str());
2199     }
2200   int nbOfCells=getNumberOfCells();
2201   bool easyAssign=true;
2202   const int *connI=_nodal_connec_index->getConstPointer();
2203   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2204   int it=start;
2205   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2206     {
2207       if(it>=0 && it<nbOfCells)
2208         {
2209           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2210         }
2211       else
2212         {
2213           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2214           throw INTERP_KERNEL::Exception(oss.str());
2215         }
2216     }
2217   if(easyAssign)
2218     {
2219       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2220       computeTypes();
2221     }
2222   else
2223     {
2224       DataArrayInt *arrOut=0,*arrIOut=0;
2225       MEDCouplingUMesh::SetPartOfIndexedArraysSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2226                                                 arrOut,arrIOut);
2227       MCAuto<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2228       setConnectivity(arrOut,arrIOut,true);
2229     }
2230 }                      
2231
2232 /*!
2233  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2234  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2235  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2236  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2237  *
2238  * \param [in] begin input start of array of node ids.
2239  * \param [in] end input end of array of node ids.
2240  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2241  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2242  */
2243 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2244 {
2245   MCAuto<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2246   checkConnectivityFullyDefined();
2247   int tmp=-1;
2248   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2249   std::vector<bool> fastFinder(sz,false);
2250   for(const int *work=begin;work!=end;work++)
2251     if(*work>=0 && *work<sz)
2252       fastFinder[*work]=true;
2253   int nbOfCells=getNumberOfCells();
2254   const int *conn=getNodalConnectivity()->getConstPointer();
2255   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2256   for(int i=0;i<nbOfCells;i++)
2257     {
2258       int ref=0,nbOfHit=0;
2259       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2260         if(*work2>=0)
2261           {
2262             ref++;
2263             if(fastFinder[*work2])
2264               nbOfHit++;
2265           }
2266       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2267         cellIdsKept->pushBackSilent(i);
2268     }
2269   cellIdsKeptArr=cellIdsKept.retn();
2270 }
2271
2272 /*!
2273  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2274  * this->getMeshDimension(), that bound some cells of \a this mesh.
2275  * The cells of lower dimension to include to the result mesh are selected basing on
2276  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2277  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2278  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2279  * created mesh shares the node coordinates array with \a this mesh. 
2280  *  \param [in] begin - the array of node ids.
2281  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2282  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2283  *         array \a begin are added, else cells whose any node is in the
2284  *         array \a begin are added.
2285  *  \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2286  *         to delete this mesh using decrRef() as it is no more needed. 
2287  *  \throw If the coordinates array is not set.
2288  *  \throw If the nodal connectivity of cells is not defined.
2289  *  \throw If any node id in \a begin is not valid.
2290  *
2291  *  \if ENABLE_EXAMPLES
2292  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2293  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2294  *  \endif
2295  */
2296 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2297 {
2298   MCAuto<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2299   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2300   MCAuto<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2301   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2302   return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2303 }
2304
2305 /*!
2306  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2307  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2308  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2309  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2310  *         by calling zipCoords().
2311  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2312  *         to delete this mesh using decrRef() as it is no more needed. 
2313  *  \throw If the coordinates array is not set.
2314  *  \throw If the nodal connectivity of cells is not defined.
2315  *
2316  *  \if ENABLE_EXAMPLES
2317  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2318  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2319  *  \endif
2320  */
2321 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2322 {
2323   DataArrayInt *desc=DataArrayInt::New();
2324   DataArrayInt *descIndx=DataArrayInt::New();
2325   DataArrayInt *revDesc=DataArrayInt::New();
2326   DataArrayInt *revDescIndx=DataArrayInt::New();
2327   //
2328   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2329   revDesc->decrRef();
2330   desc->decrRef();
2331   descIndx->decrRef();
2332   int nbOfCells=meshDM1->getNumberOfCells();
2333   const int *revDescIndxC=revDescIndx->getConstPointer();
2334   std::vector<int> boundaryCells;
2335   for(int i=0;i<nbOfCells;i++)
2336     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2337       boundaryCells.push_back(i);
2338   revDescIndx->decrRef();
2339   MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2340   return ret;
2341 }
2342
2343 /*!
2344  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2345  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2346  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2347  */
2348 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2349 {
2350   checkFullyDefined();
2351   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2352   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2353   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2354   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2355   //
2356   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2357   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2358   //
2359   MCAuto<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2360   MCAuto<DataArrayInt> faceIds=tmp->findIdsEqual(1); tmp=(DataArrayInt*)0;
2361   const int *revDescPtr=revDesc->getConstPointer();
2362   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2363   int nbOfCells=getNumberOfCells();
2364   std::vector<bool> ret1(nbOfCells,false);
2365   int sz=0;
2366   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2367     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2368       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2369   //
2370   DataArrayInt *ret2=DataArrayInt::New();
2371   ret2->alloc(sz,1);
2372   int *ret2Ptr=ret2->getPointer();
2373   sz=0;
2374   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2375     if(*it)
2376       *ret2Ptr++=sz;
2377   ret2->setName("BoundaryCells");
2378   return ret2;
2379 }
2380
2381 /*!
2382  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2383  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2384  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2385  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2386  *
2387  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2388  * 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
2389  * equals a cell in \b otherDimM1OnSameCoords.
2390  *
2391  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2392  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2393  *
2394  * \param [in] otherDimM1OnSameCoords
2395  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2396  * \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
2397  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2398  */
2399 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2400 {
2401   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2402     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2403   checkConnectivityFullyDefined();
2404   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2405   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2406     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2407   MCAuto<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2408   MCAuto<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2409   MCAuto<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2410   MCAuto<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2411   MCAuto<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2412   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2413   DataArrayInt *idsOtherInConsti=0;
2414   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2415   MCAuto<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2416   if(!b)
2417     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2418   std::set<int> s1;
2419   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2420     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2421   MCAuto<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2422   s1arr_renum1->sort();
2423   cellIdsRk0=s0arr.retn();
2424   //cellIdsRk1=s_renum1.retn();
2425   cellIdsRk1=s1arr_renum1.retn();
2426 }
2427
2428 /*!
2429  * 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
2430  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2431  * 
2432  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2433  */
2434 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2435 {
2436   MCAuto<DataArrayInt> desc=DataArrayInt::New();
2437   MCAuto<DataArrayInt> descIndx=DataArrayInt::New();
2438   MCAuto<DataArrayInt> revDesc=DataArrayInt::New();
2439   MCAuto<DataArrayInt> revDescIndx=DataArrayInt::New();
2440   //
2441   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2442   revDesc=0; desc=0; descIndx=0;
2443   MCAuto<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2444   MCAuto<DataArrayInt> part=revDescIndx2->findIdsEqual(1);
2445   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2446 }
2447
2448 /*!
2449  * Finds nodes lying on the boundary of \a this mesh.
2450  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2451  *          nodes. The caller is to delete this array using decrRef() as it is no
2452  *          more needed.
2453  *  \throw If the coordinates array is not set.
2454  *  \throw If the nodal connectivity of cells is node defined.
2455  *
2456  *  \if ENABLE_EXAMPLES
2457  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2458  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2459  *  \endif
2460  */
2461 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2462 {
2463   MCAuto<MEDCouplingUMesh> skin=computeSkin();
2464   return skin->computeFetchedNodeIds();
2465 }
2466
2467 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2468 {
2469   incrRef();
2470   return const_cast<MEDCouplingUMesh *>(this);
2471 }
2472
2473 /*!
2474  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2475  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2476  * 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.
2477  * 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.
2478  * 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.
2479  *
2480  * \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
2481  *             parameter is altered during the call.
2482  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2483  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2484  * \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.
2485  *
2486  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2487  */
2488 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2489                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2490 {
2491   typedef MCAuto<DataArrayInt> DAInt;
2492   typedef MCAuto<MEDCouplingUMesh> MCUMesh;
2493
2494   checkFullyDefined();
2495   otherDimM1OnSameCoords.checkFullyDefined();
2496   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2497     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2498   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2499     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2500
2501   // Checking star-shaped M1 group:
2502   DAInt dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2503   MCUMesh meshM2 = otherDimM1OnSameCoords.buildDescendingConnectivity(dt0, dit0, rdt0, rdit0);
2504   DAInt dsi = rdit0->deltaShiftIndex();
2505   DAInt idsTmp0 = dsi->findIdsNotInRange(-1, 3);
2506   if(idsTmp0->getNumberOfTuples())
2507     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group: group is too complex: some points (or edges) have more than two connected segments (or faces)!");
2508   dt0=0; dit0=0; rdt0=0; rdit0=0; idsTmp0=0;
2509
2510   // Get extreme nodes from the group (they won't be duplicated), ie nodes belonging to boundary cells of M1
2511   DAInt xtremIdsM2 = dsi->findIdsEqual(1); dsi = 0;
2512   MCUMesh meshM2Part = static_cast<MEDCouplingUMesh *>(meshM2->buildPartOfMySelf(xtremIdsM2->begin(), xtremIdsM2->end(),true));
2513   DAInt xtrem = meshM2Part->computeFetchedNodeIds();
2514   // Remove from the list points on the boundary of the M0 mesh (those need duplication!)
2515   dt0=DataArrayInt::New(),dit0=DataArrayInt::New(),rdt0=DataArrayInt::New(),rdit0=DataArrayInt::New();
2516   MCUMesh m0desc = buildDescendingConnectivity(dt0, dit0, rdt0, rdit0); dt0=0; dit0=0; rdt0=0;
2517   dsi = rdit0->deltaShiftIndex();
2518   DAInt boundSegs = dsi->findIdsEqual(1);   // boundary segs/faces of the M0 mesh
2519   MCUMesh m0descSkin = static_cast<MEDCouplingUMesh *>(m0desc->buildPartOfMySelf(boundSegs->begin(),boundSegs->end(), true));
2520   DAInt fNodes = m0descSkin->computeFetchedNodeIds();
2521   // In 3D, some points on the boundary of M0 still need duplication:
2522   DAInt notDup = 0;
2523   if (getMeshDimension() == 3)
2524     {
2525       DAInt dnu1=DataArrayInt::New(), dnu2=DataArrayInt::New(), dnu3=DataArrayInt::New(), dnu4=DataArrayInt::New();
2526       MCUMesh m0descSkinDesc = m0descSkin->buildDescendingConnectivity(dnu1, dnu2, dnu3, dnu4);
2527       dnu1=0;dnu2=0;dnu3=0;dnu4=0;
2528       DataArrayInt * corresp=0;
2529       meshM2->areCellsIncludedIn(m0descSkinDesc,2,corresp);
2530       DAInt validIds = corresp->findIdsInRange(0, meshM2->getNumberOfCells());
2531       corresp->decrRef();
2532       if (validIds->getNumberOfTuples())
2533         {
2534           MCUMesh m1IntersecSkin = static_cast<MEDCouplingUMesh *>(m0descSkinDesc->buildPartOfMySelf(validIds->begin(), validIds->end(), true));
2535           DAInt notDuplSkin = m1IntersecSkin->findBoundaryNodes();
2536           DAInt fNodes1 = fNodes->buildSubstraction(notDuplSkin);
2537           notDup = xtrem->buildSubstraction(fNodes1);
2538         }
2539       else
2540         notDup = xtrem->buildSubstraction(fNodes);
2541     }
2542   else
2543     notDup = xtrem->buildSubstraction(fNodes);
2544
2545   // Now compute cells around group (i.e. cells where we will do the propagation to identify the two sub-sets delimited by the group)
2546   DAInt m1Nodes = otherDimM1OnSameCoords.computeFetchedNodeIds();
2547   DAInt dupl = m1Nodes->buildSubstraction(notDup);
2548   DAInt cellsAroundGroup = getCellIdsLyingOnNodes(dupl->begin(), dupl->end(), false);  // false= take cell in, even if not all nodes are in notDup
2549
2550   //
2551   MCUMesh m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellsAroundGroup->begin(),cellsAroundGroup->end(),true));
2552   int nCells2 = m0Part2->getNumberOfCells();
2553   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2554   MCUMesh m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2555
2556   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2557   DataArrayInt *tmp00=0,*tmp11=0;
2558   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2559   DAInt neighInit00(tmp00);
2560   DAInt neighIInit00(tmp11);
2561   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2562   DataArrayInt *idsTmp=0;
2563   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2564   DAInt ids(idsTmp);
2565   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2566   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2567   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2568   DataArrayInt *tmp0=0,*tmp1=0;
2569   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2570   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2571   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2572   DAInt neigh00(tmp0);
2573   DAInt neighI00(tmp1);
2574
2575   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2576   int seed = 0, nIter = 0;
2577   int nIterMax = nCells2+1; // Safety net for the loop
2578   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2579   hitCells->fillWithValue(-1);
2580   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2581   cellsToModifyConn0_torenum->alloc(0,1);
2582   while (nIter < nIterMax)
2583     {
2584       DAInt t = hitCells->findIdsEqual(-1);
2585       if (!t->getNumberOfTuples())
2586         break;
2587       // Connex zone without the crack (to compute the next seed really)
2588       int dnu;
2589       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2590       int cnt = 0;
2591       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2592         hitCells->setIJ(*ptr,0,1);
2593       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2594       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2595       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2596       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2597       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2598       DAInt nonHitCells = hitCells->findIdsEqual(-1);
2599       DAInt intersec = nonHitCells->buildIntersection(comple);
2600       if (intersec->getNumberOfTuples())
2601         { seed = intersec->getIJ(0,0); }
2602       else
2603         { break; }
2604       nIter++;
2605     }
2606   if (nIter >= nIterMax)
2607     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2608
2609   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2610   cellsToModifyConn0_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2611   cellsToModifyConn1_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2612   //
2613   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2614   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2615   nodeIdsToDuplicate=dupl.retn();
2616 }
2617
2618 /*!
2619  * This method operates a modification of the connectivity and coords in \b this.
2620  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2621  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2622  * 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
2623  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2624  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2625  * 
2626  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2627  * 
2628  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2629  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2630  */
2631 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2632 {
2633   int nbOfNodes=getNumberOfNodes();
2634   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2635   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2636 }
2637
2638 /*!
2639  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2640  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2641  *
2642  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2643  *
2644  * \sa renumberNodesInConn
2645  */
2646 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2647 {
2648   checkConnectivityFullyDefined();
2649   int *conn(getNodalConnectivity()->getPointer());
2650   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2651   int nbOfCells(getNumberOfCells());
2652   for(int i=0;i<nbOfCells;i++)
2653     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2654       {
2655         int& node=conn[iconn];
2656         if(node>=0)//avoid polyhedron separator
2657           {
2658             node+=offset;
2659           }
2660       }
2661   _nodal_connec->declareAsNew();
2662   updateTime();
2663 }
2664
2665 /*!
2666  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2667  *  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
2668  *  of a big mesh.
2669  */
2670 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2671 {
2672   checkConnectivityFullyDefined();
2673   int *conn(getNodalConnectivity()->getPointer());
2674   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2675   int nbOfCells(getNumberOfCells());
2676   for(int i=0;i<nbOfCells;i++)
2677     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2678       {
2679         int& node=conn[iconn];
2680         if(node>=0)//avoid polyhedron separator
2681           {
2682             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2683             if(it!=newNodeNumbersO2N.end())
2684               {
2685                 node=(*it).second;
2686               }
2687             else
2688               {
2689                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2690                 throw INTERP_KERNEL::Exception(oss.str());
2691               }
2692           }
2693       }
2694   _nodal_connec->declareAsNew();
2695   updateTime();
2696 }
2697
2698 /*!
2699  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2700  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2701  * This method is a generalization of shiftNodeNumbersInConn().
2702  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2703  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2704  *         this->getNumberOfNodes(), in "Old to New" mode. 
2705  *         See \ref numbering for more info on renumbering modes.
2706  *  \throw If the nodal connectivity of cells is not defined.
2707  *
2708  *  \if ENABLE_EXAMPLES
2709  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2710  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2711  *  \endif
2712  */
2713 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2714 {
2715   checkConnectivityFullyDefined();
2716   int *conn=getNodalConnectivity()->getPointer();
2717   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2718   int nbOfCells(getNumberOfCells());
2719   for(int i=0;i<nbOfCells;i++)
2720     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2721       {
2722         int& node=conn[iconn];
2723         if(node>=0)//avoid polyhedron separator
2724           {
2725             node=newNodeNumbersO2N[node];
2726           }
2727       }
2728   _nodal_connec->declareAsNew();
2729   updateTime();
2730 }
2731
2732 /*!
2733  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2734  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2735  * This method is an specialization of \ref MEDCoupling::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2736  * 
2737  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2738  */
2739 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2740 {
2741   checkConnectivityFullyDefined();
2742   int *conn=getNodalConnectivity()->getPointer();
2743   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2744   int nbOfCells=getNumberOfCells();
2745   for(int i=0;i<nbOfCells;i++)
2746     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2747       {
2748         int& node=conn[iconn];
2749         if(node>=0)//avoid polyhedron separator
2750           {
2751             node+=delta;
2752           }
2753       }
2754   _nodal_connec->declareAsNew();
2755   updateTime();
2756 }
2757
2758 /*!
2759  * This method operates a modification of the connectivity in \b this.
2760  * 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.
2761  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2762  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2763  * 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
2764  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2765  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2766  * 
2767  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2768  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2769  * 
2770  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2771  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2772  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2773  */
2774 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2775 {
2776   checkConnectivityFullyDefined();
2777   std::map<int,int> m;
2778   int val=offset;
2779   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2780     m[*work]=val;
2781   int *conn=getNodalConnectivity()->getPointer();
2782   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2783   int nbOfCells=getNumberOfCells();
2784   for(int i=0;i<nbOfCells;i++)
2785     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2786       {
2787         int& node=conn[iconn];
2788         if(node>=0)//avoid polyhedron separator
2789           {
2790             std::map<int,int>::iterator it=m.find(node);
2791             if(it!=m.end())
2792               node=(*it).second;
2793           }
2794       }
2795   updateTime();
2796 }
2797
2798 /*!
2799  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2800  *
2801  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2802  * After the call of this method the number of cells remains the same as before.
2803  *
2804  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2805  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2806  * be strictly in [0;this->getNumberOfCells()).
2807  *
2808  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2809  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2810  * should be contained in[0;this->getNumberOfCells()).
2811  * 
2812  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2813  * \param check
2814  */
2815 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2816 {
2817   checkConnectivityFullyDefined();
2818   int nbCells=getNumberOfCells();
2819   const int *array=old2NewBg;
2820   if(check)
2821     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2822   //
2823   const int *conn=_nodal_connec->getConstPointer();
2824   const int *connI=_nodal_connec_index->getConstPointer();
2825   MCAuto<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2826   MCAuto<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2827   const int *n2oPtr=n2o->begin();
2828   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
2829   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2830   newConn->copyStringInfoFrom(*_nodal_connec);
2831   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
2832   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2833   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2834   //
2835   int *newC=newConn->getPointer();
2836   int *newCI=newConnI->getPointer();
2837   int loc=0;
2838   newCI[0]=loc;
2839   for(int i=0;i<nbCells;i++)
2840     {
2841       int pos=n2oPtr[i];
2842       int nbOfElts=connI[pos+1]-connI[pos];
2843       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2844       loc+=nbOfElts;
2845       newCI[i+1]=loc;
2846     }
2847   //
2848   setConnectivity(newConn,newConnI);
2849   if(check)
2850     free(const_cast<int *>(array));
2851 }
2852
2853 /*!
2854  * Finds cells whose bounding boxes intersect a given bounding box.
2855  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2856  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2857  *         zMax (if in 3D). 
2858  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2859  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2860  *         extent of the bounding box of cell to produce an addition to this bounding box.
2861  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2862  *         cells. The caller is to delete this array using decrRef() as it is no more
2863  *         needed. 
2864  *  \throw If the coordinates array is not set.
2865  *  \throw If the nodal connectivity of cells is not defined.
2866  *
2867  *  \if ENABLE_EXAMPLES
2868  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2869  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2870  *  \endif
2871  */
2872 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2873 {
2874   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2875   if(getMeshDimension()==-1)
2876     {
2877       elems->pushBackSilent(0);
2878       return elems.retn();
2879     }
2880   int dim=getSpaceDimension();
2881   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2882   const int* conn      = getNodalConnectivity()->getConstPointer();
2883   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2884   const double* coords = getCoords()->getConstPointer();
2885   int nbOfCells=getNumberOfCells();
2886   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2887     {
2888       for (int i=0; i<dim; i++)
2889         {
2890           elem_bb[i*2]=std::numeric_limits<double>::max();
2891           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2892         }
2893
2894       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2895         {
2896           int node= conn[inode];
2897           if(node>=0)//avoid polyhedron separator
2898             {
2899               for (int idim=0; idim<dim; idim++)
2900                 {
2901                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2902                     {
2903                       elem_bb[idim*2] = coords[node*dim+idim] ;
2904                     }
2905                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2906                     {
2907                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2908                     }
2909                 }
2910             }
2911         }
2912       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2913         elems->pushBackSilent(ielem);
2914     }
2915   return elems.retn();
2916 }
2917
2918 /*!
2919  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2920  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2921  * added in 'elems' parameter.
2922  */
2923 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2924 {
2925   MCAuto<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2926   if(getMeshDimension()==-1)
2927     {
2928       elems->pushBackSilent(0);
2929       return elems.retn();
2930     }
2931   int dim=getSpaceDimension();
2932   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2933   const int* conn      = getNodalConnectivity()->getConstPointer();
2934   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2935   const double* coords = getCoords()->getConstPointer();
2936   int nbOfCells=getNumberOfCells();
2937   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2938     {
2939       for (int i=0; i<dim; i++)
2940         {
2941           elem_bb[i*2]=std::numeric_limits<double>::max();
2942           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2943         }
2944
2945       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2946         {
2947           int node= conn[inode];
2948           if(node>=0)//avoid polyhedron separator
2949             {
2950               for (int idim=0; idim<dim; idim++)
2951                 {
2952                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2953                     {
2954                       elem_bb[idim*2] = coords[node*dim+idim] ;
2955                     }
2956                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2957                     {
2958                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2959                     }
2960                 }
2961             }
2962         }
2963       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2964         elems->pushBackSilent(ielem);
2965     }
2966   return elems.retn();
2967 }
2968
2969 /*!
2970  * Returns a type of a cell by its id.
2971  *  \param [in] cellId - the id of the cell of interest.
2972  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2973  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2974  */
2975 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2976 {
2977   const int *ptI=_nodal_connec_index->getConstPointer();
2978   const int *pt=_nodal_connec->getConstPointer();
2979   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2980     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2981   else
2982     {
2983       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2984       throw INTERP_KERNEL::Exception(oss.str());
2985     }
2986 }
2987
2988 /*!
2989  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2990  * This method does not throw exception if geometric type \a type is not in \a this.
2991  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2992  * The coordinates array is not considered here.
2993  *
2994  * \param [in] type the geometric type
2995  * \return cell ids in this having geometric type \a type.
2996  */
2997 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2998 {
2999
3000   MCAuto<DataArrayInt> ret=DataArrayInt::New();
3001   ret->alloc(0,1);
3002   checkConnectivityFullyDefined();
3003   int nbCells=getNumberOfCells();
3004   int mdim=getMeshDimension();
3005   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
3006   if(mdim!=(int)cm.getDimension())
3007     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
3008   const int *ptI=_nodal_connec_index->getConstPointer();
3009   const int *pt=_nodal_connec->getConstPointer();
3010   for(int i=0;i<nbCells;i++)
3011     {
3012       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
3013         ret->pushBackSilent(i);
3014     }
3015   return ret.retn();
3016 }
3017
3018 /*!
3019  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
3020  */
3021 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
3022 {
3023   const int *ptI=_nodal_connec_index->getConstPointer();
3024   const int *pt=_nodal_connec->getConstPointer();
3025   int nbOfCells=getNumberOfCells();
3026   int ret=0;
3027   for(int i=0;i<nbOfCells;i++)
3028     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
3029       ret++;
3030   return ret;
3031 }
3032
3033 /*!
3034  * Returns the nodal connectivity of a given cell.
3035  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
3036  * all returned node ids can be used in getCoordinatesOfNode().
3037  *  \param [in] cellId - an id of the cell of interest.
3038  *  \param [in,out] conn - a vector where the node ids are appended. It is not
3039  *         cleared before the appending.
3040  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
3041  */
3042 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
3043 {
3044   const int *ptI=_nodal_connec_index->getConstPointer();
3045   const int *pt=_nodal_connec->getConstPointer();
3046   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
3047     if(*w>=0)
3048       conn.push_back(*w);
3049 }
3050
3051 std::string MEDCouplingUMesh::simpleRepr() const
3052 {
3053   static const char msg0[]="No coordinates specified !";
3054   std::ostringstream ret;
3055   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
3056   ret << "Description of mesh : \"" << getDescription() << "\"\n";
3057   int tmpp1,tmpp2;
3058   double tt=getTime(tmpp1,tmpp2);
3059   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
3060   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
3061   if(_mesh_dim>=-1)
3062     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
3063   else
3064     { ret << " Mesh dimension has not been set or is invalid !"; }
3065   if(_coords!=0)
3066     {
3067       const int spaceDim=getSpaceDimension();
3068       ret << spaceDim << "\nInfo attached on space dimension : ";
3069       for(int i=0;i<spaceDim;i++)
3070         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
3071       ret << "\n";
3072     }
3073   else
3074     ret << msg0 << "\n";
3075   ret << "Number of nodes : ";
3076   if(_coords!=0)
3077     ret << getNumberOfNodes() << "\n";
3078   else
3079     ret << msg0 << "\n";
3080   ret << "Number of cells : ";
3081   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3082     ret << getNumberOfCells() << "\n";
3083   else
3084     ret << "No connectivity specified !" << "\n";
3085   ret << "Cell types present : ";
3086   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3087     {
3088       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3089       ret << cm.getRepr() << " ";
3090     }
3091   ret << "\n";
3092   return ret.str();
3093 }
3094
3095 std::string MEDCouplingUMesh::advancedRepr() const
3096 {
3097   std::ostringstream ret;
3098   ret << simpleRepr();
3099   ret << "\nCoordinates array : \n___________________\n\n";
3100   if(_coords)
3101     _coords->reprWithoutNameStream(ret);
3102   else
3103     ret << "No array set !\n";
3104   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3105   reprConnectivityOfThisLL(ret);
3106   return ret.str();
3107 }
3108
3109 /*!
3110  * This method returns a C++ code that is a dump of \a this.
3111  * This method will throw if this is not fully defined.
3112  */
3113 std::string MEDCouplingUMesh::cppRepr() const
3114 {
3115   static const char coordsName[]="coords";
3116   static const char connName[]="conn";
3117   static const char connIName[]="connI";
3118   checkFullyDefined();
3119   std::ostringstream ret; ret << "// coordinates" << std::endl;
3120   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3121   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3122   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3123   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3124   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3125   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3126   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3127   return ret.str();
3128 }
3129
3130 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3131 {
3132   std::ostringstream ret;
3133   reprConnectivityOfThisLL(ret);
3134   return ret.str();
3135 }
3136
3137 /*!
3138  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3139  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3140  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3141  * some algos).
3142  * 
3143  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3144  * 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
3145  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3146  */
3147 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3148 {
3149   int mdim=getMeshDimension();
3150   if(mdim<0)
3151     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3152   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3153   MCAuto<DataArrayInt> tmp1,tmp2;
3154   bool needToCpyCT=true;
3155   if(!_nodal_connec)
3156     {
3157       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3158       needToCpyCT=false;
3159     }
3160   else
3161     {
3162       tmp1=_nodal_connec;
3163       tmp1->incrRef();
3164     }
3165   if(!_nodal_connec_index)
3166     {
3167       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3168       needToCpyCT=false;
3169     }
3170   else
3171     {
3172       tmp2=_nodal_connec_index;
3173       tmp2->incrRef();
3174     }
3175   ret->setConnectivity(tmp1,tmp2,false);
3176   if(needToCpyCT)
3177     ret->_types=_types;
3178   if(!_coords)
3179     {
3180       MCAuto<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3181       ret->setCoords(coords);
3182     }
3183   else
3184     ret->setCoords(_coords);
3185   return ret.retn();
3186 }
3187
3188 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3189 {
3190   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3191     {
3192       int nbOfCells=getNumberOfCells();
3193       const int *c=_nodal_connec->getConstPointer();
3194       const int *ci=_nodal_connec_index->getConstPointer();
3195       for(int i=0;i<nbOfCells;i++)
3196         {
3197           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3198           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3199           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3200           stream << "\n";
3201         }
3202     }
3203   else
3204     stream << "Connectivity not defined !\n";
3205 }
3206
3207 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3208 {
3209   const int *ptI=_nodal_connec_index->getConstPointer();
3210   const int *pt=_nodal_connec->getConstPointer();
3211   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3212     return ptI[cellId+1]-ptI[cellId]-1;
3213   else
3214     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3215 }
3216
3217 /*!
3218  * Returns types of cells of the specified part of \a this mesh.
3219  * This method avoids computing sub-mesh explicitely to get its types.
3220  *  \param [in] begin - an array of cell ids of interest.
3221  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3222  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3223  *         describing the cell types. 
3224  *  \throw If the coordinates array is not set.
3225  *  \throw If the nodal connectivity of cells is not defined.
3226  *  \sa getAllGeoTypes()
3227  */
3228 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3229 {
3230   checkFullyDefined();
3231   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3232   const int *conn=_nodal_connec->getConstPointer();
3233   const int *connIndex=_nodal_connec_index->getConstPointer();
3234   for(const int *w=begin;w!=end;w++)
3235     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3236   return ret;
3237 }
3238
3239 /*!
3240  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3241  * Optionally updates
3242  * a set of types of cells constituting \a this mesh. 
3243  * This method is for advanced users having prepared their connectivity before. For
3244  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3245  *  \param [in] conn - the nodal connectivity array. 
3246  *  \param [in] connIndex - the nodal connectivity index array.
3247  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3248  *         mesh is updated.
3249  */
3250 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3251 {
3252   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3253   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3254   if(isComputingTypes)
3255     computeTypes();
3256   declareAsNew();
3257 }
3258
3259 /*!
3260  * Copy constructor. If 'deepCopy' is false \a this is a shallow copy of other.
3261  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3262  */
3263 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3264     _nodal_connec(0),_nodal_connec_index(0),
3265     _types(other._types)
3266 {
3267   if(other._nodal_connec)
3268     _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCopy);
3269   if(other._nodal_connec_index)
3270     _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCopy);
3271 }
3272
3273 MEDCouplingUMesh::~MEDCouplingUMesh()
3274 {
3275   if(_nodal_connec)
3276     _nodal_connec->decrRef();
3277   if(_nodal_connec_index)
3278     _nodal_connec_index->decrRef();
3279 }
3280
3281 /*!
3282  * Recomputes a set of cell types of \a this mesh. For more info see
3283  * \ref MEDCouplingUMeshNodalConnectivity.
3284  */
3285 void MEDCouplingUMesh::computeTypes()
3286 {
3287   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3288 }
3289
3290 /*!
3291  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3292  */
3293 void MEDCouplingUMesh::checkFullyDefined() const
3294 {
3295   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3296     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3297 }
3298
3299 /*!
3300  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3301  */
3302 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3303 {
3304   if(!_nodal_connec_index || !_nodal_connec)
3305     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3306 }
3307
3308 /*!
3309  * Returns a number of cells constituting \a this mesh. 
3310  *  \return int - the number of cells in \a this mesh.
3311  *  \throw If the nodal connectivity of cells is not defined.
3312  */
3313 int MEDCouplingUMesh::getNumberOfCells() const
3314
3315   if(_nodal_connec_index)
3316     return _nodal_connec_index->getNumberOfTuples()-1;
3317   else
3318     if(_mesh_dim==-1)
3319       return 1;
3320     else
3321       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3322 }
3323
3324 /*!
3325  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3326  * mesh. For more info see \ref meshes.
3327  *  \return int - the dimension of \a this mesh.
3328  *  \throw If the mesh dimension is not defined using setMeshDimension().
3329  */
3330 int MEDCouplingUMesh::getMeshDimension() const
3331 {
3332   if(_mesh_dim<-1)
3333     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3334   return _mesh_dim;
3335 }
3336
3337 /*!
3338  * Returns a length of the nodal connectivity array.
3339  * This method is for test reason. Normally the integer returned is not useable by
3340  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3341  *  \return int - the length of the nodal connectivity array.
3342  */
3343 int MEDCouplingUMesh::getNodalConnectivityArrayLen() const
3344 {
3345   return _nodal_connec->getNbOfElems();
3346 }
3347
3348 /*!
3349  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3350  */
3351 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3352 {
3353   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3354   tinyInfo.push_back(getMeshDimension());
3355   tinyInfo.push_back(getNumberOfCells());
3356   if(_nodal_connec)
3357     tinyInfo.push_back(getNodalConnectivityArrayLen());
3358   else
3359     tinyInfo.push_back(-1);
3360 }
3361
3362 /*!
3363  * First step of unserialization process.
3364  */
3365 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3366 {
3367   return tinyInfo[6]<=0;
3368 }
3369
3370 /*!
3371  * Second step of serialization process.
3372  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3373  * \param a1
3374  * \param a2
3375  * \param littleStrings
3376  */
3377 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3378 {
3379   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3380   if(tinyInfo[5]!=-1)
3381     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3382 }
3383
3384 /*!
3385  * Third and final step of serialization process.
3386  */
3387 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3388 {
3389   MEDCouplingPointSet::serialize(a1,a2);
3390   if(getMeshDimension()>-1)
3391     {
3392       a1=DataArrayInt::New();
3393       a1->alloc(getNodalConnectivityArrayLen()+getNumberOfCells()+1,1);
3394       int *ptA1=a1->getPointer();
3395       const int *conn=getNodalConnectivity()->getConstPointer();
3396       const int *index=getNodalConnectivityIndex()->getConstPointer();
3397       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3398       std::copy(conn,conn+getNodalConnectivityArrayLen(),ptA1);
3399     }
3400   else
3401     a1=0;
3402 }
3403
3404 /*!
3405  * Second and final unserialization process.
3406  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3407  */
3408 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3409 {
3410   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3411   setMeshDimension(tinyInfo[5]);
3412   if(tinyInfo[7]!=-1)
3413     {
3414       // Connectivity
3415       const int *recvBuffer=a1->getConstPointer();
3416       MCAuto<DataArrayInt> myConnecIndex=DataArrayInt::New();
3417       myConnecIndex->alloc(tinyInfo[6]+1,1);
3418       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3419       MCAuto<DataArrayInt> myConnec=DataArrayInt::New();
3420       myConnec->alloc(tinyInfo[7],1);
3421       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3422       setConnectivity(myConnec, myConnecIndex);
3423     }
3424 }
3425
3426 /*!
3427  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelfSlice.
3428  * CellIds are given using range specified by a start an end and step.
3429  */
3430 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice(int start, int end, int step) const
3431 {
3432   checkFullyDefined();
3433   int ncell=getNumberOfCells();
3434   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3435   ret->_mesh_dim=_mesh_dim;
3436   ret->setCoords(_coords);
3437   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice : ");
3438   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3439   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3440   int work=start;
3441   const int *conn=_nodal_connec->getConstPointer();
3442   const int *connIndex=_nodal_connec_index->getConstPointer();
3443   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3444     {
3445       if(work>=0 && work<ncell)
3446         {
3447           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3448         }
3449       else
3450         {
3451           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoordsSlice : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3452           throw INTERP_KERNEL::Exception(oss.str());
3453         }
3454     }
3455   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3456   int *newConnPtr=newConn->getPointer();
3457   std::set<INTERP_KERNEL::NormalizedCellType> types;
3458   work=start;
3459   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3460     {
3461       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3462       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3463     }
3464   ret->setConnectivity(newConn,newConnI,false);
3465   ret->_types=types;
3466   ret->copyTinyInfoFrom(this);
3467   return ret.retn();
3468 }
3469
3470 /*!
3471  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3472  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3473  * The return newly allocated mesh will share the same coordinates as \a this.
3474  */
3475 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3476 {
3477   checkConnectivityFullyDefined();
3478   int ncell=getNumberOfCells();
3479   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3480   ret->_mesh_dim=_mesh_dim;
3481   ret->setCoords(_coords);
3482   std::size_t nbOfElemsRet=std::distance(begin,end);
3483   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3484   connIndexRet[0]=0;
3485   const int *conn=_nodal_connec->getConstPointer();
3486   const int *connIndex=_nodal_connec_index->getConstPointer();
3487   int newNbring=0;
3488   for(const int *work=begin;work!=end;work++,newNbring++)
3489     {
3490       if(*work>=0 && *work<ncell)
3491         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3492       else
3493         {
3494           free(connIndexRet);
3495           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3496           throw INTERP_KERNEL::Exception(oss.str());
3497         }
3498     }
3499   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3500   int *connRetWork=connRet;
3501   std::set<INTERP_KERNEL::NormalizedCellType> types;
3502   for(const int *work=begin;work!=end;work++)
3503     {
3504       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3505       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3506     }
3507   MCAuto<DataArrayInt> connRetArr=DataArrayInt::New();
3508   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3509   MCAuto<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3510   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3511   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3512   ret->_types=types;
3513   ret->copyTinyInfoFrom(this);
3514   return ret.retn();
3515 }
3516
3517 /*!
3518  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3519  * mesh.<br>
3520  * For 1D cells, the returned field contains lengths.<br>
3521  * For 2D cells, the returned field contains areas.<br>
3522  * For 3D cells, the returned field contains volumes.
3523  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3524  *         orientation, i.e. the volume is always positive.
3525  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3526  *         and one time . The caller is to delete this field using decrRef() as it is no
3527  *         more needed.
3528  */
3529 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3530 {
3531   std::string name="MeasureOfMesh_";
3532   name+=getName();
3533   int nbelem=getNumberOfCells();
3534   MCAuto<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3535   field->setName(name);
3536   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3537   array->alloc(nbelem,1);
3538   double *area_vol=array->getPointer();
3539   field->setArray(array) ; array=0;
3540   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3541   field->synchronizeTimeWithMesh();
3542   if(getMeshDimension()!=-1)
3543     {
3544       int ipt;
3545       INTERP_KERNEL::NormalizedCellType type;
3546       int dim_space=getSpaceDimension();
3547       const double *coords=getCoords()->getConstPointer();
3548       const int *connec=getNodalConnectivity()->getConstPointer();
3549       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3550       for(int iel=0;iel<nbelem;iel++)
3551         {
3552           ipt=connec_index[iel];
3553           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3554           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);
3555         }
3556       if(isAbs)
3557         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3558     }
3559   else
3560     {
3561       area_vol[0]=std::numeric_limits<double>::max();
3562     }
3563   return field.retn();
3564 }
3565
3566 /*!
3567  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3568  * mesh.<br>
3569  * For 1D cells, the returned array contains lengths.<br>
3570  * For 2D cells, the returned array contains areas.<br>
3571  * For 3D cells, the returned array contains volumes.
3572  * This method avoids building explicitly a part of \a this mesh to perform the work.
3573  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3574  *         orientation, i.e. the volume is always positive.
3575  *  \param [in] begin - an array of cell ids of interest.
3576  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3577  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3578  *          delete this array using decrRef() as it is no more needed.
3579  * 
3580  *  \if ENABLE_EXAMPLES
3581  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3582  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3583  *  \endif
3584  *  \sa getMeasureField()
3585  */
3586 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3587 {
3588   std::string name="PartMeasureOfMesh_";
3589   name+=getName();
3590   int nbelem=(int)std::distance(begin,end);
3591   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3592   array->setName(name);
3593   array->alloc(nbelem,1);
3594   double *area_vol=array->getPointer();
3595   if(getMeshDimension()!=-1)
3596     {
3597       int ipt;
3598       INTERP_KERNEL::NormalizedCellType type;
3599       int dim_space=getSpaceDimension();
3600       const double *coords=getCoords()->getConstPointer();
3601       const int *connec=getNodalConnectivity()->getConstPointer();
3602       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3603       for(const int *iel=begin;iel!=end;iel++)
3604         {
3605           ipt=connec_index[*iel];
3606           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3607           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3608         }
3609       if(isAbs)
3610         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3611     }
3612   else
3613     {
3614       area_vol[0]=std::numeric_limits<double>::max();
3615     }
3616   return array.retn();
3617 }
3618
3619 /*!
3620  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3621  * \a this one. The returned field contains the dual cell volume for each corresponding
3622  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3623  *  the dual mesh in P1 sens of \a this.<br>
3624  * For 1D cells, the returned field contains lengths.<br>
3625  * For 2D cells, the returned field contains areas.<br>
3626  * For 3D cells, the returned field contains volumes.
3627  * This method is useful to check "P1*" conservative interpolators.
3628  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3629  *         orientation, i.e. the volume is always positive.
3630  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3631  *          nodes and one time. The caller is to delete this array using decrRef() as
3632  *          it is no more needed.
3633  */
3634 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3635 {
3636   MCAuto<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3637   std::string name="MeasureOnNodeOfMesh_";
3638   name+=getName();
3639   int nbNodes=getNumberOfNodes();
3640   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3641   double cst=1./((double)getMeshDimension()+1.);
3642   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3643   array->alloc(nbNodes,1);
3644   double *valsToFill=array->getPointer();
3645   std::fill(valsToFill,valsToFill+nbNodes,0.);
3646   const double *values=tmp->getArray()->getConstPointer();
3647   MCAuto<DataArrayInt> da=DataArrayInt::New();
3648   MCAuto<DataArrayInt> daInd=DataArrayInt::New();
3649   getReverseNodalConnectivity(da,daInd);
3650   const int *daPtr=da->getConstPointer();
3651   const int *daIPtr=daInd->getConstPointer();
3652   for(int i=0;i<nbNodes;i++)
3653     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3654       valsToFill[i]+=cst*values[*cell];
3655   ret->setMesh(this);
3656   ret->setArray(array);
3657   return ret.retn();
3658 }
3659
3660 /*!
3661  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3662  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3663  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3664  * and are normalized.
3665  * <br> \a this can be either 
3666  * - a  2D mesh in 2D or 3D space or 
3667  * - an 1D mesh in 2D space.
3668  * 
3669  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3670  *          cells and one time. The caller is to delete this field using decrRef() as
3671  *          it is no more needed.
3672  *  \throw If the nodal connectivity of cells is not defined.
3673  *  \throw If the coordinates array is not set.
3674  *  \throw If the mesh dimension is not set.
3675  *  \throw If the mesh and space dimension is not as specified above.
3676  */
3677 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3678 {
3679   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3680     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3681   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3682   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3683   int nbOfCells=getNumberOfCells();
3684   int nbComp=getMeshDimension()+1;
3685   array->alloc(nbOfCells,nbComp);
3686   double *vals=array->getPointer();
3687   const int *connI=_nodal_connec_index->getConstPointer();
3688   const int *conn=_nodal_connec->getConstPointer();
3689   const double *coords=_coords->getConstPointer();
3690   if(getMeshDimension()==2)
3691     {
3692       if(getSpaceDimension()==3)
3693         {
3694           MCAuto<DataArrayDouble> loc=computeCellCenterOfMass();
3695           const double *locPtr=loc->getConstPointer();
3696           for(int i=0;i<nbOfCells;i++,vals+=3)
3697             {
3698               int offset=connI[i];
3699               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3700               double n=INTERP_KERNEL::norm<3>(vals);
3701               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3702             }
3703         }
3704       else
3705         {
3706           MCAuto<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3707           const double *isAbsPtr=isAbs->getArray()->begin();
3708           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3709             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3710         }
3711     }
3712   else//meshdimension==1
3713     {
3714       double tmp[2];
3715       for(int i=0;i<nbOfCells;i++)
3716         {
3717           int offset=connI[i];
3718           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3719           double n=INTERP_KERNEL::norm<2>(tmp);
3720           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3721           *vals++=-tmp[1];
3722           *vals++=tmp[0];
3723         }
3724     }
3725   ret->setArray(array);
3726   ret->setMesh(this);
3727   ret->synchronizeTimeWithSupport();
3728   return ret.retn();
3729 }
3730
3731 /*!
3732  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3733  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3734  * and are normalized.
3735  * <br> \a this can be either 
3736  * - a  2D mesh in 2D or 3D space or 
3737  * - an 1D mesh in 2D space.
3738  * 
3739  * This method avoids building explicitly a part of \a this mesh to perform the work.
3740  *  \param [in] begin - an array of cell ids of interest.
3741  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3742  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3743  *          cells and one time. The caller is to delete this field using decrRef() as
3744  *          it is no more needed.
3745  *  \throw If the nodal connectivity of cells is not defined.
3746  *  \throw If the coordinates array is not set.
3747  *  \throw If the mesh dimension is not set.
3748  *  \throw If the mesh and space dimension is not as specified above.
3749  *  \sa buildOrthogonalField()
3750  *
3751  *  \if ENABLE_EXAMPLES
3752  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3753  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3754  *  \endif
3755  */
3756 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3757 {
3758   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3759     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3760   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3761   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3762   std::size_t nbelems=std::distance(begin,end);
3763   int nbComp=getMeshDimension()+1;
3764   array->alloc((int)nbelems,nbComp);
3765   double *vals=array->getPointer();
3766   const int *connI=_nodal_connec_index->getConstPointer();
3767   const int *conn=_nodal_connec->getConstPointer();
3768   const double *coords=_coords->getConstPointer();
3769   if(getMeshDimension()==2)
3770     {
3771       if(getSpaceDimension()==3)
3772         {
3773           MCAuto<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3774           const double *locPtr=loc->getConstPointer();
3775           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3776             {
3777               int offset=connI[*i];
3778               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3779               double n=INTERP_KERNEL::norm<3>(vals);
3780               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3781             }
3782         }
3783       else
3784         {
3785           for(std::size_t i=0;i<nbelems;i++)
3786             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3787         }
3788     }
3789   else//meshdimension==1
3790     {
3791       double tmp[2];
3792       for(const int *i=begin;i!=end;i++)
3793         {
3794           int offset=connI[*i];
3795           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3796           double n=INTERP_KERNEL::norm<2>(tmp);
3797           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3798           *vals++=-tmp[1];
3799           *vals++=tmp[0];
3800         }
3801     }
3802   ret->setArray(array);
3803   ret->setMesh(this);
3804   ret->synchronizeTimeWithSupport();
3805   return ret.retn();
3806 }
3807
3808 /*!
3809  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3810  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3811  * and are \b not normalized.
3812  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3813  *          cells and one time. The caller is to delete this field using decrRef() as
3814  *          it is no more needed.
3815  *  \throw If the nodal connectivity of cells is not defined.
3816  *  \throw If the coordinates array is not set.
3817  *  \throw If \a this->getMeshDimension() != 1.
3818  *  \throw If \a this mesh includes cells of type other than SEG2.
3819  */
3820 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3821 {
3822   if(getMeshDimension()!=1)
3823     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3824   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3825     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3826   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3827   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3828   int nbOfCells=getNumberOfCells();
3829   int spaceDim=getSpaceDimension();
3830   array->alloc(nbOfCells,spaceDim);
3831   double *pt=array->getPointer();
3832   const double *coo=getCoords()->getConstPointer();
3833   std::vector<int> conn;
3834   conn.reserve(2);
3835   for(int i=0;i<nbOfCells;i++)
3836     {
3837       conn.resize(0);
3838       getNodeIdsOfCell(i,conn);
3839       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3840     }
3841   ret->setArray(array);
3842   ret->setMesh(this);
3843   ret->synchronizeTimeWithSupport();
3844   return ret.retn();
3845 }
3846
3847 /*!
3848  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3849  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3850  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3851  * from. If a result face is shared by two 3D cells, then the face in included twice in
3852  * the result mesh.
3853  *  \param [in] origin - 3 components of a point defining location of the plane.
3854  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3855  *         must be greater than 1e-6.
3856  *  \param [in] eps - half-thickness of the plane.
3857  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3858  *         producing correspondent 2D cells. The caller is to delete this array
3859  *         using decrRef() as it is no more needed.
3860  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3861  *         not share the node coordinates array with \a this mesh. The caller is to
3862  *         delete this mesh using decrRef() as it is no more needed.  
3863  *  \throw If the coordinates array is not set.
3864  *  \throw If the nodal connectivity of cells is not defined.
3865  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3866  *  \throw If magnitude of \a vec is less than 1e-6.
3867  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3868  *  \throw If \a this includes quadratic cells.
3869  */
3870 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3871 {
3872   checkFullyDefined();
3873   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3874     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3875   MCAuto<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3876   if(candidates->empty())
3877     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3878   std::vector<int> nodes;
3879   DataArrayInt *cellIds1D=0;
3880   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3881   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3882   MCAuto<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3883   MCAuto<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3884   MCAuto<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3885   MCAuto<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3886   MCAuto<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3887   revDesc2=0; revDescIndx2=0;
3888   MCAuto<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3889   revDesc1=0; revDescIndx1=0;
3890   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3891   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3892   //
3893   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3894   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3895     cut3DCurve[*it]=-1;
3896   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3897   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3898   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3899                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3900                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3901   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3902   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3903   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3904   if(cellIds2->empty())
3905     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3906   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3907   ret->setCoords(mDesc1->getCoords());
3908   ret->setConnectivity(conn,connI,true);
3909   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3910   return ret.retn();
3911 }
3912
3913 /*!
3914  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3915 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
3916 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3917 the result mesh.
3918  *  \param [in] origin - 3 components of a point defining location of the plane.
3919  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3920  *         must be greater than 1e-6.
3921  *  \param [in] eps - half-thickness of the plane.
3922  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3923  *         producing correspondent segments. The caller is to delete this array
3924  *         using decrRef() as it is no more needed.
3925  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3926  *         mesh in 3D space. This mesh does not share the node coordinates array with
3927  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3928  *         no more needed. 
3929  *  \throw If the coordinates array is not set.
3930  *  \throw If the nodal connectivity of cells is not defined.
3931  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3932  *  \throw If magnitude of \a vec is less than 1e-6.
3933  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3934  *  \throw If \a this includes quadratic cells.
3935  */
3936 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3937 {
3938   checkFullyDefined();
3939   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3940     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3941   MCAuto<DataArrayInt> candidates(getCellIdsCrossingPlane(origin,vec,eps));
3942   if(candidates->empty())
3943     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3944   std::vector<int> nodes;
3945   DataArrayInt *cellIds1D(0);
3946   MCAuto<MEDCouplingUMesh> subMesh(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3947   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3948   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
3949   MCAuto<MEDCouplingUMesh> mDesc1(subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3950   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3951   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
3952   //
3953   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3954   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3955     cut3DCurve[*it]=-1;
3956   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3957   int ncellsSub=subMesh->getNumberOfCells();
3958   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3959   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3960                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3961                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3962   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3963   conn->alloc(0,1);
3964   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3965   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3966   for(int i=0;i<ncellsSub;i++)
3967     {
3968       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3969         {
3970           if(cut3DSurf[i].first!=-2)
3971             {
3972               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3973               connI->pushBackSilent(conn->getNumberOfTuples());
3974               cellIds2->pushBackSilent(i);
3975             }
3976           else
3977             {
3978               int cellId3DSurf=cut3DSurf[i].second;
3979               int offset=nodalI[cellId3DSurf]+1;
3980               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3981               for(int j=0;j<nbOfEdges;j++)
3982                 {
3983                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3984                   connI->pushBackSilent(conn->getNumberOfTuples());
3985                   cellIds2->pushBackSilent(cellId3DSurf);
3986                 }
3987             }
3988         }
3989     }
3990   if(cellIds2->empty())
3991     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3992   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3993   ret->setCoords(mDesc1->getCoords());
3994   ret->setConnectivity(conn,connI,true);
3995   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3996   return ret.retn();
3997 }
3998
3999 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::clipSingle3DCellByPlane(const double origin[3], const double vec[3], double eps) const
4000 {
4001   checkFullyDefined();
4002   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4003     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
4004   if(getNumberOfCells()!=1)
4005     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works only on mesh containing exactly one cell !");
4006   //
4007   std::vector<int> nodes;
4008   findNodesOnPlane(origin,vec,eps,nodes);
4009   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),desc2(DataArrayInt::New()),descIndx1(DataArrayInt::New()),descIndx2(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDesc2(DataArrayInt::New()),revDescIndx1(DataArrayInt::New()),revDescIndx2(DataArrayInt::New());
4010   MCAuto<MEDCouplingUMesh> mDesc2(buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2));//meshDim==2 spaceDim==3
4011   revDesc2=0; revDescIndx2=0;
4012   MCAuto<MEDCouplingUMesh> mDesc1(mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
4013   revDesc1=0; revDescIndx1=0;
4014   DataArrayInt *cellIds1D(0);
4015   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
4016   MCAuto<DataArrayInt> cellIds1DTmp(cellIds1D);
4017   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
4018   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
4019     cut3DCurve[*it]=-1;
4020   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
4021   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
4022   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->begin(),mDesc2->getNodalConnectivityIndex()->begin(),
4023                               mDesc1->getNodalConnectivity()->begin(),mDesc1->getNodalConnectivityIndex()->begin(),
4024                               desc1->begin(),descIndx1->begin(),cut3DSurf);
4025   MCAuto<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New());
4026   connI->pushBackSilent(0); conn->alloc(0,1);
4027   {
4028     MCAuto<DataArrayInt> cellIds2(DataArrayInt::New()); cellIds2->alloc(0,1);
4029     assemblyForSplitFrom3DSurf(cut3DSurf,desc2->begin(),descIndx2->begin(),conn,connI,cellIds2);
4030     if(cellIds2->empty())
4031       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
4032   }
4033   std::vector<std::vector<int> > res;
4034   buildSubCellsFromCut(cut3DSurf,desc2->begin(),descIndx2->begin(),mDesc1->getCoords()->begin(),eps,res);
4035   std::size_t sz(res.size());
4036   if(res.size()==mDesc1->getNumberOfCells())
4037     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane : cell is not clipped !");
4038   for(std::size_t i=0;i<sz;i++)
4039     {
4040       conn->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
4041       conn->insertAtTheEnd(res[i].begin(),res[i].end());
4042       connI->pushBackSilent(conn->getNumberOfTuples());
4043     }
4044   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
4045   ret->setCoords(mDesc1->getCoords());
4046   ret->setConnectivity(conn,connI,true);
4047   int nbCellsRet(ret->getNumberOfCells());
4048   //
4049   MCAuto<DataArrayDouble> vec2(DataArrayDouble::New()); vec2->alloc(1,3); std::copy(vec,vec+3,vec2->getPointer());
4050   MCAuto<MEDCouplingFieldDouble> ortho(ret->buildOrthogonalField());
4051   MCAuto<DataArrayDouble> ortho2(ortho->getArray()->selectByTupleIdSafeSlice(0,1,1));
4052   MCAuto<DataArrayDouble> dott(DataArrayDouble::Dot(ortho2,vec2));
4053   MCAuto<DataArrayDouble> ccm(ret->computeCellCenterOfMass());
4054   MCAuto<DataArrayDouble> occm;
4055   {
4056     MCAuto<DataArrayDouble> pt(DataArrayDouble::New()); pt->alloc(1,3); std::copy(origin,origin+3,pt->getPointer());
4057     occm=DataArrayDouble::Substract(ccm,pt);
4058   }
4059   vec2=DataArrayDouble::New(); vec2->alloc(nbCellsRet,3);
4060   vec2->setPartOfValuesSimple1(vec[0],0,nbCellsRet,1,0,1,1); vec2->setPartOfValuesSimple1(vec[1],0,nbCellsRet,1,1,2,1); vec2->setPartOfValuesSimple1(vec[2],0,nbCellsRet,1,2,3,1);
4061   MCAuto<DataArrayDouble> dott2(DataArrayDouble::Dot(occm,vec2));
4062   //
4063   const int *cPtr(ret->getNodalConnectivity()->begin()),*ciPtr(ret->getNodalConnectivityIndex()->begin());
4064   MCAuto<MEDCouplingUMesh> ret2(MEDCouplingUMesh::New("Clip3D",3));
4065   ret2->setCoords(mDesc1->getCoords());
4066   MCAuto<DataArrayInt> conn2(DataArrayInt::New()),conn2I(DataArrayInt::New());
4067   conn2I->pushBackSilent(0); conn2->alloc(0,1);
4068   std::vector<int> cell0(1,(int)INTERP_KERNEL::NORM_POLYHED);
4069   std::vector<int> cell1(1,(int)INTERP_KERNEL::NORM_POLYHED);
4070   if(dott->getIJ(0,0)>0)
4071     {
4072       cell0.insert(cell0.end(),cPtr+1,cPtr+ciPtr[1]);
4073       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell1,cell1.end()));
4074     }
4075   else
4076     {
4077       cell1.insert(cell1.end(),cPtr+1,cPtr+ciPtr[1]);
4078       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell0,cell0.end()));
4079     }
4080   for(int i=1;i<nbCellsRet;i++)
4081     {
4082       if(dott2->getIJ(i,0)<0)
4083         {
4084           if(ciPtr[i+1]-ciPtr[i]>=4)
4085             {
4086               cell0.push_back(-1);
4087               cell0.insert(cell0.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
4088             }
4089         }
4090       else
4091         {
4092           if(ciPtr[i+1]-ciPtr[i]>=4)
4093             {
4094               cell1.push_back(-1);
4095               cell1.insert(cell1.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
4096             }
4097         }
4098     }
4099   conn2->insertAtTheEnd(cell0.begin(),cell0.end());
4100   conn2I->pushBackSilent(conn2->getNumberOfTuples());
4101   conn2->insertAtTheEnd(cell1.begin(),cell1.end());
4102   conn2I->pushBackSilent(conn2->getNumberOfTuples());
4103   ret2->setConnectivity(conn2,conn2I,true);
4104   ret2->checkConsistencyLight();
4105   ret2->writeVTK("ret2.vtu");
4106   ret2->orientCorrectlyPolyhedrons();
4107   return ret2;
4108 }
4109
4110 /*!
4111  * Finds cells whose bounding boxes intersect a given plane.
4112  *  \param [in] origin - 3 components of a point defining location of the plane.
4113  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
4114  *         must be greater than 1e-6.
4115  *  \param [in] eps - half-thickness of the plane.
4116  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
4117  *         cells. The caller is to delete this array using decrRef() as it is no more
4118  *         needed.
4119  *  \throw If the coordinates array is not set.
4120  *  \throw If the nodal connectivity of cells is not defined.
4121  *  \throw If \a this->getSpaceDimension() != 3.
4122  *  \throw If magnitude of \a vec is less than 1e-6.
4123  *  \sa buildSlice3D()
4124  */
4125 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
4126 {
4127   checkFullyDefined();
4128   if(getSpaceDimension()!=3)
4129     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
4130   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4131   if(normm<1e-6)
4132     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4133   double vec2[3];
4134   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
4135   double angle=acos(vec[2]/normm);
4136   MCAuto<DataArrayInt> cellIds;
4137   double bbox[6];
4138   if(angle>eps)
4139     {
4140       MCAuto<DataArrayDouble> coo=_coords->deepCopy();
4141       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
4142       if(normm2/normm>1e-6)
4143         DataArrayDouble::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer(),coo->getPointer());
4144       MCAuto<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
4145       mw->setCoords(coo);
4146       mw->getBoundingBox(bbox);
4147       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4148       cellIds=mw->getCellsInBoundingBox(bbox,eps);
4149     }
4150   else
4151     {
4152       getBoundingBox(bbox);
4153       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
4154       cellIds=getCellsInBoundingBox(bbox,eps);
4155     }
4156   return cellIds.retn();
4157 }
4158
4159 /*!
4160  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
4161  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
4162  * No consideration of coordinate is done by this method.
4163  * 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)
4164  * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be usefull.
4165  */
4166 bool MEDCouplingUMesh::isContiguous1D() const
4167 {
4168   if(getMeshDimension()!=1)
4169     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
4170   int nbCells=getNumberOfCells();
4171   if(nbCells<1)
4172     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
4173   const int *connI(_nodal_connec_index->begin()),*conn(_nodal_connec->begin());
4174   int ref=conn[connI[0]+2];
4175   for(int i=1;i<nbCells;i++)
4176     {
4177       if(conn[connI[i]+1]!=ref)
4178         return false;
4179       ref=conn[connI[i]+2];
4180     }
4181   return true;
4182 }
4183
4184 /*!
4185  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4186  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4187  * \param pt reference point of the line
4188  * \param v normalized director vector of the line
4189  * \param eps max precision before throwing an exception
4190  * \param res output of size this->getNumberOfCells
4191  */
4192 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4193 {
4194   if(getMeshDimension()!=1)
4195     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4196   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4197     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4198   if(getSpaceDimension()!=3)
4199     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4200   MCAuto<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4201   const double *fPtr=f->getArray()->getConstPointer();
4202   double tmp[3];
4203   for(int i=0;i<getNumberOfCells();i++)
4204     {
4205       const double *tmp1=fPtr+3*i;
4206       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4207       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4208       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4209       double n1=INTERP_KERNEL::norm<3>(tmp);
4210       n1/=INTERP_KERNEL::norm<3>(tmp1);
4211       if(n1>eps)
4212         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4213     }
4214   const double *coo=getCoords()->getConstPointer();
4215   for(int i=0;i<getNumberOfNodes();i++)
4216     {
4217       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4218       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4219       res[i]=std::accumulate(tmp,tmp+3,0.);
4220     }
4221 }
4222
4223 /*!
4224  * 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. 
4225  * \a this is expected to be a mesh so that its space dimension is equal to its
4226  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4227  * 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).
4228  *
4229  * 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
4230  * 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).
4231  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4232  *
4233  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4234  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4235  *
4236  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4237  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4238  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4239  * \return the positive value of the distance.
4240  * \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
4241  * dimension - 1.
4242  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4243  */
4244 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4245 {
4246   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4247   if(meshDim!=spaceDim-1)
4248     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4249   if(meshDim!=2 && meshDim!=1)
4250     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4251   checkFullyDefined();
4252   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4253     { 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()); }
4254   DataArrayInt *ret1=0;
4255   MCAuto<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4256   MCAuto<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4257   MCAuto<DataArrayInt> ret1Safe(ret1);
4258   cellId=*ret1Safe->begin();
4259   return *ret0->begin();
4260 }
4261
4262 /*!
4263  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4264  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4265  * 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
4266  * 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).
4267  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4268  * 
4269  * \a this is expected to be a mesh so that its space dimension is equal to its
4270  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4271  * 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).
4272  *
4273  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4274  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4275  *
4276  * \param [in] pts the list of points in which each tuple represents a point
4277  * \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.
4278  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4279  * \throw if number of components of \a pts is not equal to the space dimension.
4280  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4281  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4282  */
4283 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4284 {
4285   if(!pts)
4286     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4287   pts->checkAllocated();
4288   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4289   if(meshDim!=spaceDim-1)
4290     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4291   if(meshDim!=2 && meshDim!=1)
4292     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4293   if(pts->getNumberOfComponents()!=spaceDim)
4294     {
4295       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4296       throw INTERP_KERNEL::Exception(oss.str());
4297     }
4298   checkFullyDefined();
4299   int nbCells=getNumberOfCells();
4300   if(nbCells==0)
4301     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4302   int nbOfPts=pts->getNumberOfTuples();
4303   MCAuto<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4304   MCAuto<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4305   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4306   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4307   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4308   const double *bbox(bboxArr->begin());
4309   switch(spaceDim)
4310   {
4311     case 3:
4312       {
4313         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4314         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4315           {
4316             double x=std::numeric_limits<double>::max();
4317             std::vector<int> elems;
4318             myTree.getMinDistanceOfMax(ptsPtr,x);
4319             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4320             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4321           }
4322         break;
4323       }
4324     case 2:
4325       {
4326         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4327         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4328           {
4329             double x=std::numeric_limits<double>::max();
4330             std::vector<int> elems;
4331             myTree.getMinDistanceOfMax(ptsPtr,x);
4332             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4333             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4334           }
4335         break;
4336       }
4337     default:
4338       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4339   }
4340   cellIds=ret1.retn();
4341   return ret0.retn();
4342 }
4343
4344 /// @cond INTERNAL
4345
4346 /*!
4347  * \param [in] pt the start pointer (included) of the coordinates of the point
4348  * \param [in] cellIdsBg the start pointer (included) of cellIds
4349  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4350  * \param [in] nc nodal connectivity
4351  * \param [in] ncI nodal connectivity index
4352  * \param [in,out] ret0 the min distance between \a this and the external input point
4353  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4354  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4355  */
4356 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)
4357 {
4358   cellId=-1;
4359   ret0=std::numeric_limits<double>::max();
4360   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4361     {
4362       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4363       {
4364         case INTERP_KERNEL::NORM_TRI3:
4365           {
4366             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4367             if(tmp<ret0)
4368               { ret0=tmp; cellId=*zeCell; }
4369             break;
4370           }
4371         case INTERP_KERNEL::NORM_QUAD4:
4372         case INTERP_KERNEL::NORM_POLYGON:
4373           {
4374             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4375             if(tmp<ret0)
4376               { ret0=tmp; cellId=*zeCell; }
4377             break;
4378           }
4379         default:
4380           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4381       }
4382     }
4383 }
4384
4385 /*!
4386  * \param [in] pt the start pointer (included) of the coordinates of the point
4387  * \param [in] cellIdsBg the start pointer (included) of cellIds
4388  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4389  * \param [in] nc nodal connectivity
4390  * \param [in] ncI nodal connectivity index
4391  * \param [in,out] ret0 the min distance between \a this and the external input point
4392  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4393  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4394  */
4395 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)
4396 {
4397   cellId=-1;
4398   ret0=std::numeric_limits<double>::max();
4399   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4400     {
4401       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4402       {
4403         case INTERP_KERNEL::NORM_SEG2:
4404           {
4405             std::size_t uselessEntry=0;
4406             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4407             tmp=sqrt(tmp);
4408             if(tmp<ret0)
4409               { ret0=tmp; cellId=*zeCell; }
4410             break;
4411           }
4412         default:
4413           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4414       }
4415     }
4416 }
4417 /// @endcond
4418
4419 /*!
4420  * Finds cells in contact with a ball (i.e. a point with precision). 
4421  * 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.
4422  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4423  *
4424  * \warning This method is suitable if the caller intends to evaluate only one
4425  *          point, for more points getCellsContainingPoints() is recommended as it is
4426  *          faster. 
4427  *  \param [in] pos - array of coordinates of the ball central point.
4428  *  \param [in] eps - ball radius.
4429  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4430  *         if there are no such cells.
4431  *  \throw If the coordinates array is not set.
4432  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4433  */
4434 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4435 {
4436   std::vector<int> elts;
4437   getCellsContainingPoint(pos,eps,elts);
4438   if(elts.empty())
4439     return -1;
4440   return elts.front();
4441 }
4442
4443 /*!
4444  * Finds cells in contact with a ball (i.e. a point with precision).
4445  * 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.
4446  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4447  * \warning This method is suitable if the caller intends to evaluate only one
4448  *          point, for more points getCellsContainingPoints() is recommended as it is
4449  *          faster. 
4450  *  \param [in] pos - array of coordinates of the ball central point.
4451  *  \param [in] eps - ball radius.
4452  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4453  *         before inserting ids.
4454  *  \throw If the coordinates array is not set.
4455  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4456  *
4457  *  \if ENABLE_EXAMPLES
4458  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4459  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4460  *  \endif
4461  */
4462 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4463 {
4464   MCAuto<DataArrayInt> eltsUg,eltsIndexUg;
4465   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4466   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4467 }
4468
4469 /// @cond INTERNAL
4470
4471 namespace MEDCoupling
4472 {
4473   template<const int SPACEDIMM>
4474   class DummyClsMCUG
4475   {
4476   public:
4477     static const int MY_SPACEDIM=SPACEDIMM;
4478     static const int MY_MESHDIM=8;
4479     typedef int MyConnType;
4480     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4481     // begin
4482     // useless, but for windows compilation ...
4483     const double* getCoordinatesPtr() const { return 0; }
4484     const int* getConnectivityPtr() const { return 0; }
4485     const int* getConnectivityIndexPtr() const { return 0; }
4486     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4487     // end
4488   };
4489
4490   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MCAuto<INTERP_KERNEL::Node>,int>& m)
4491   {
4492     INTERP_KERNEL::Edge *ret(0);
4493     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]));
4494     m[n0]=bg[0]; m[n1]=bg[1];
4495     switch(typ)
4496     {
4497       case INTERP_KERNEL::NORM_SEG2:
4498         {
4499           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4500           break;
4501         }
4502       case INTERP_KERNEL::NORM_SEG3:
4503         {
4504           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4505           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4506           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4507           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4508           bool colinearity(inters.areColinears());
4509           delete e1; delete e2;
4510           if(colinearity)
4511             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4512           else
4513             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4514           break;
4515         }
4516       default:
4517         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4518     }
4519     return ret;
4520   }
4521
4522   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4523   {
4524     INTERP_KERNEL::Edge *ret=0;
4525     switch(typ)
4526     {
4527       case INTERP_KERNEL::NORM_SEG2:
4528         {
4529           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4530           break;
4531         }
4532       case INTERP_KERNEL::NORM_SEG3:
4533         {
4534           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4535           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4536           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4537           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4538           bool colinearity=inters.areColinears();
4539           delete e1; delete e2;
4540           if(colinearity)
4541             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4542           else
4543             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4544           mapp2[bg[2]].second=false;
4545           break;
4546         }
4547       default:
4548         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4549     }
4550     return ret;
4551   }
4552
4553   /*!
4554    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4555    * the global mesh 'mDesc'.
4556    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4557    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4558    */
4559   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4560                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4561   {
4562     mapp.clear();
4563     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.
4564     const double *coo=mDesc->getCoords()->getConstPointer();
4565     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4566     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4567     std::set<int> s;
4568     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4569       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4570     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4571       {
4572         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4573         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4574       }
4575     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4576     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4577       {
4578         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4579         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4580       }
4581     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4582       {
4583         if((*it2).second.second)
4584           mapp[(*it2).second.first]=(*it2).first;
4585         ((*it2).second.first)->decrRef();
4586       }
4587     return ret;
4588   }
4589
4590   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4591   {
4592     if(nodeId>=offset2)
4593       {
4594         int locId=nodeId-offset2;
4595         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4596       }
4597     if(nodeId>=offset1)
4598       {
4599         int locId=nodeId-offset1;
4600         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4601       }
4602     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4603   }
4604
4605   /**
4606    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4607    */
4608   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4609                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4610                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4611   {
4612     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4613       {
4614         int eltId1=abs(*desc1)-1;
4615         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4616           {
4617             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4618             if(it==mappRev.end())
4619               {
4620                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4621                 mapp[node]=*it1;
4622                 mappRev[*it1]=node;
4623               }
4624           }
4625       }
4626   }
4627 }
4628
4629 /// @endcond
4630
4631 template<int SPACEDIM>
4632 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4633                                                    double eps, MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4634 {
4635   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4636   int *eltsIndexPtr(eltsIndex->getPointer());
4637   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4638   const double *bbox(bboxArr->begin());
4639   int nbOfCells=getNumberOfCells();
4640   const int *conn=_nodal_connec->getConstPointer();
4641   const int *connI=_nodal_connec_index->getConstPointer();
4642   double bb[2*SPACEDIM];
4643   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4644   for(int i=0;i<nbOfPoints;i++)
4645     {
4646       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4647       for(int j=0;j<SPACEDIM;j++)
4648         {
4649           bb[2*j]=pos[SPACEDIM*i+j];
4650           bb[2*j+1]=pos[SPACEDIM*i+j];
4651         }
4652       std::vector<int> candidates;
4653       myTree.getIntersectingElems(bb,candidates);
4654       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4655         {
4656           int sz(connI[(*iter)+1]-connI[*iter]-1);
4657           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4658           bool status(false);
4659           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4660             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4661           else
4662             {
4663               if(SPACEDIM!=2)
4664                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4665               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4666               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4667               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4668               INTERP_KERNEL::QuadraticPolygon *pol(0);
4669               for(int j=0;j<sz;j++)
4670                 {
4671                   int nodeId(conn[connI[*iter]+1+j]);
4672                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4673                 }
4674               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4675                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4676               else
4677                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4678               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4679               double a(0.),b(0.),c(0.);
4680               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4681               status=pol->isInOrOut2(n);
4682               delete pol; n->decrRef();
4683             }
4684           if(status)
4685             {
4686               eltsIndexPtr[i+1]++;
4687               elts->pushBackSilent(*iter);
4688             }
4689         }
4690     }
4691 }
4692 /*!
4693  * Finds cells in contact with several balls (i.e. points with precision).
4694  * This method is an extension of getCellContainingPoint() and
4695  * getCellsContainingPoint() for the case of multiple points.
4696  * 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.
4697  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4698  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4699  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4700  *         this->getSpaceDimension() * \a nbOfPoints 
4701  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4702  *  \param [in] eps - radius of balls (i.e. the precision).
4703  *  \param [out] elts - vector returning ids of found cells.
4704  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4705  *         dividing cell ids in \a elts into groups each referring to one
4706  *         point. Its every element (except the last one) is an index pointing to the
4707  *         first id of a group of cells. For example cells in contact with the *i*-th
4708  *         point are described by following range of indices:
4709  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4710  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4711  *         Number of cells in contact with the *i*-th point is
4712  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4713  *  \throw If the coordinates array is not set.
4714  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4715  *
4716  *  \if ENABLE_EXAMPLES
4717  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4718  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4719  *  \endif
4720  */
4721 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4722                                                 MCAuto<DataArrayInt>& elts, MCAuto<DataArrayInt>& eltsIndex) const
4723 {
4724   int spaceDim=getSpaceDimension();
4725   int mDim=getMeshDimension();
4726   if(spaceDim==3)
4727     {
4728       if(mDim==3)
4729         {
4730           const double *coords=_coords->getConstPointer();
4731           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4732         }
4733       /*else if(mDim==2)
4734         {
4735
4736         }*/
4737       else
4738         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4739     }
4740   else if(spaceDim==2)
4741     {
4742       if(mDim==2)
4743         {
4744           const double *coords=_coords->getConstPointer();
4745           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4746         }
4747       else
4748         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4749     }
4750   else if(spaceDim==1)
4751     {
4752       if(mDim==1)
4753         {
4754           const double *coords=_coords->getConstPointer();
4755           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4756         }
4757       else
4758         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4759     }
4760   else
4761     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4762 }
4763
4764 /*!
4765  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4766  * least two its edges intersect each other anywhere except their extremities. An
4767  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4768  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4769  *         cleared before filling in.
4770  *  \param [in] eps - precision.
4771  *  \throw If \a this->getMeshDimension() != 2.
4772  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4773  */
4774 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4775 {
4776   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4777   if(getMeshDimension()!=2)
4778     throw INTERP_KERNEL::Exception(msg);
4779   int spaceDim=getSpaceDimension();
4780   if(spaceDim!=2 && spaceDim!=3)
4781     throw INTERP_KERNEL::Exception(msg);
4782   const int *conn=_nodal_connec->getConstPointer();
4783   const int *connI=_nodal_connec_index->getConstPointer();
4784   int nbOfCells=getNumberOfCells();
4785   std::vector<double> cell2DinS2;
4786   for(int i=0;i<nbOfCells;i++)
4787     {
4788       int offset=connI[i];
4789       int nbOfNodesForCell=connI[i+1]-offset-1;
4790       if(nbOfNodesForCell<=3)
4791         continue;
4792       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4793       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4794       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4795         cells.push_back(i);
4796       cell2DinS2.clear();
4797     }
4798 }
4799
4800 /*!
4801  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4802  *
4803  * 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.
4804  * 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.
4805  * 
4806  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4807  * This convex envelop is computed using Jarvis march algorithm.
4808  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4809  * 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)
4810  * 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.
4811  *
4812  * \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.
4813  * \sa MEDCouplingUMesh::colinearize2D
4814  */
4815 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4816 {
4817   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4818     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4819   checkFullyDefined();
4820   const double *coords=getCoords()->getConstPointer();
4821   int nbOfCells=getNumberOfCells();
4822   MCAuto<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4823   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4824   MCAuto<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4825   int *workIndexOut=nodalConnecIndexOut->getPointer();
4826   *workIndexOut=0;
4827   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4828   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4829   std::set<INTERP_KERNEL::NormalizedCellType> types;
4830   MCAuto<DataArrayInt> isChanged(DataArrayInt::New());
4831   isChanged->alloc(0,1);
4832   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4833     {
4834       int pos=nodalConnecOut->getNumberOfTuples();
4835       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4836         isChanged->pushBackSilent(i);
4837       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4838       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4839     }
4840   if(isChanged->empty())
4841     return 0;
4842   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4843   _types=types;
4844   return isChanged.retn();
4845 }
4846
4847 /*!
4848  * This method is \b NOT const because it can modify \a this.
4849  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4850  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4851  * \param policy specifies the type of extrusion chosen:
4852  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4853  *   will be repeated to build each level
4854  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4855  *   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
4856  *   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
4857  *   arc.
4858  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4859  */
4860 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4861 {
4862   checkFullyDefined();
4863   mesh1D->checkFullyDefined();
4864   if(!mesh1D->isContiguous1D())
4865     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4866   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4867     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4868   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4869     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4870   if(mesh1D->getMeshDimension()!=1)
4871     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4872   bool isQuad=false;
4873   if(isPresenceOfQuadratic())
4874     {
4875       if(mesh1D->isFullyQuadratic())
4876         isQuad=true;
4877       else
4878         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4879     }
4880   int oldNbOfNodes(getNumberOfNodes());
4881   MCAuto<DataArrayDouble> newCoords;
4882   switch(policy)
4883   {
4884     case 0:
4885       {
4886         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4887         break;
4888       }
4889     case 1:
4890       {
4891         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4892         break;
4893       }
4894     default:
4895       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4896   }
4897   setCoords(newCoords);
4898   MCAuto<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4899   updateTime();
4900   return ret.retn();
4901 }
4902
4903 /*!
4904  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4905  * If it is not the case an exception will be thrown.
4906  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4907  * intersection of plane defined by ('origin','vec').
4908  * This method has one in/out parameter : 'cut3DCurve'.
4909  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4910  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4911  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4912  * This method will throw an exception if \a this contains a non linear segment.
4913  */
4914 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4915 {
4916   checkFullyDefined();
4917   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4918     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4919   int ncells=getNumberOfCells();
4920   int nnodes=getNumberOfNodes();
4921   double vec2[3],vec3[3],vec4[3];
4922   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4923   if(normm<1e-6)
4924     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4925   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4926   const int *conn=_nodal_connec->getConstPointer();
4927   const int *connI=_nodal_connec_index->getConstPointer();
4928   const double *coo=_coords->getConstPointer();
4929   std::vector<double> addCoo;
4930   for(int i=0;i<ncells;i++)
4931     {
4932       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4933         {
4934           if(cut3DCurve[i]==-2)
4935             {
4936               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4937               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];
4938               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4939               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4940               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4941                 {
4942                   const double *st2=coo+3*st;
4943                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4944                   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]));
4945                   if(pos>eps && pos<1-eps)
4946                     {
4947                       int nNode=((int)addCoo.size())/3;
4948                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4949                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4950                       cut3DCurve[i]=nnodes+nNode;
4951                     }
4952                 }
4953             }
4954         }
4955       else
4956         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4957     }
4958   if(!addCoo.empty())
4959     {
4960       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4961       MCAuto<DataArrayDouble> coo2=DataArrayDouble::New();
4962       coo2->alloc(newNbOfNodes,3);
4963       double *tmp=coo2->getPointer();
4964       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4965       std::copy(addCoo.begin(),addCoo.end(),tmp);
4966       DataArrayDouble::SetArrayIn(coo2,_coords);
4967     }
4968 }
4969
4970 /*!
4971  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4972  * \param mesh1D is the input 1D mesh used for translation computation.
4973  * \return newCoords new coords filled by this method. 
4974  */
4975 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4976 {
4977   int oldNbOfNodes=getNumberOfNodes();
4978   int nbOf1DCells=mesh1D->getNumberOfCells();
4979   int spaceDim=getSpaceDimension();
4980   DataArrayDouble *ret=DataArrayDouble::New();
4981   std::vector<bool> isQuads;
4982   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4983   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4984   double *retPtr=ret->getPointer();
4985   const double *coords=getCoords()->getConstPointer();
4986   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4987   std::vector<int> v;
4988   std::vector<double> c;
4989   double vec[3];
4990   v.reserve(3);
4991   c.reserve(6);
4992   for(int i=0;i<nbOf1DCells;i++)
4993     {
4994       v.resize(0);
4995       mesh1D->getNodeIdsOfCell(i,v);
4996       c.resize(0);
4997       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4998       mesh1D->getCoordinatesOfNode(v[0],c);
4999       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
5000       for(int j=0;j<oldNbOfNodes;j++)
5001         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
5002       if(isQuad)
5003         {
5004           c.resize(0);
5005           mesh1D->getCoordinatesOfNode(v[1],c);
5006           mesh1D->getCoordinatesOfNode(v[0],c);
5007           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
5008           for(int j=0;j<oldNbOfNodes;j++)
5009             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
5010         }
5011     }
5012   ret->copyStringInfoFrom(*getCoords());
5013   return ret;
5014 }
5015
5016 /*!
5017  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
5018  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
5019  * \return newCoords new coords filled by this method. 
5020  */
5021 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
5022 {
5023   if(mesh1D->getSpaceDimension()==2)
5024     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
5025   if(mesh1D->getSpaceDimension()==3)
5026     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
5027   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
5028 }
5029
5030 /*!
5031  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
5032  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
5033  * \return newCoords new coords filled by this method. 
5034  */
5035 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
5036 {
5037   if(isQuad)
5038     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
5039   int oldNbOfNodes=getNumberOfNodes();
5040   int nbOf1DCells=mesh1D->getNumberOfCells();
5041   if(nbOf1DCells<2)
5042     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
5043   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
5044   int nbOfLevsInVec=nbOf1DCells+1;
5045   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
5046   double *retPtr=ret->getPointer();
5047   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
5048   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5049   MCAuto<DataArrayDouble> tmp2=getCoords()->deepCopy();
5050   tmp->setCoords(tmp2);
5051   const double *coo1D=mesh1D->getCoords()->getConstPointer();
5052   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
5053   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
5054   for(int i=1;i<nbOfLevsInVec;i++)
5055     {
5056       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
5057       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
5058       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
5059       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
5060       tmp->translate(vec);
5061       double tmp3[2],radius,alpha,alpha0;
5062       const double *p0=i+1<nbOfLevsInVec?begin:third;
5063       const double *p1=i+1<nbOfLevsInVec?end:begin;
5064       const double *p2=i+1<nbOfLevsInVec?third:end;
5065       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
5066       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]);
5067       double angle=acos(cosangle/(radius*radius));
5068       tmp->rotate(end,0,angle);
5069       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
5070     }
5071   return ret.retn();
5072 }
5073
5074 /*!
5075  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
5076  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
5077  * \return newCoords new coords filled by this method. 
5078  */
5079 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
5080 {
5081   if(isQuad)
5082     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
5083   int oldNbOfNodes=getNumberOfNodes();
5084   int nbOf1DCells=mesh1D->getNumberOfCells();
5085   if(nbOf1DCells<2)
5086     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
5087   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
5088   int nbOfLevsInVec=nbOf1DCells+1;
5089   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
5090   double *retPtr=ret->getPointer();
5091   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
5092   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5093   MCAuto<DataArrayDouble> tmp2=getCoords()->deepCopy();
5094   tmp->setCoords(tmp2);
5095   const double *coo1D=mesh1D->getCoords()->getConstPointer();
5096   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
5097   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
5098   for(int i=1;i<nbOfLevsInVec;i++)
5099     {
5100       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
5101       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
5102       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
5103       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
5104       tmp->translate(vec);
5105       double tmp3[2],radius,alpha,alpha0;
5106       const double *p0=i+1<nbOfLevsInVec?begin:third;
5107       const double *p1=i+1<nbOfLevsInVec?end:begin;
5108       const double *p2=i+1<nbOfLevsInVec?third:end;
5109       double vecPlane[3]={
5110         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
5111         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
5112         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
5113       };
5114       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
5115       if(norm>1.e-7)
5116         {
5117           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
5118           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
5119           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
5120           double s2=norm2;
5121           double c2=cos(asin(s2));
5122           double m[3][3]={
5123             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
5124             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
5125             {-vec2[1]*s2, vec2[0]*s2, c2}
5126           };
5127           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]};
5128           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]};
5129           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]};
5130           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
5131           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]);
5132           double angle=acos(cosangle/(radius*radius));
5133           tmp->rotate(end,vecPlane,angle);
5134         }
5135       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
5136     }
5137   return ret.retn();
5138 }
5139
5140 /*!
5141  * This method is private because not easy to use for end user. This method is const contrary to
5142  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
5143  * the coords sorted slice by slice.
5144  * \param isQuad specifies presence of quadratic cells.
5145  */
5146 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
5147 {
5148   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
5149   int nbOf2DCells(getNumberOfCells());
5150   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
5151   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
5152   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5153   MCAuto<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
5154   newConnI->alloc(nbOf3DCells+1,1);
5155   int *newConnIPtr(newConnI->getPointer());
5156   *newConnIPtr++=0;
5157   std::vector<int> newc;
5158   for(int j=0;j<nbOf2DCells;j++)
5159     {
5160       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
5161       *newConnIPtr++=(int)newc.size();
5162     }
5163   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
5164   int *newConnPtr(newConn->getPointer());
5165   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
5166   newConnIPtr=newConnI->getPointer();
5167   for(int iz=0;iz<nbOf1DCells;iz++)
5168     {
5169       if(iz!=0)
5170         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
5171       const int *posOfTypeOfCell(newConnIPtr);
5172       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
5173         {
5174           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
5175           if(icell!=*posOfTypeOfCell)
5176             {
5177               if(*iter!=-1)
5178                 *newConnPtr=(*iter)+iz*deltaPerLev;
5179               else
5180                 *newConnPtr=-1;
5181             }
5182           else
5183             {
5184               *newConnPtr=*iter;
5185               posOfTypeOfCell++;
5186             }
5187         }
5188     }
5189   ret->setConnectivity(newConn,newConnI,true);
5190   ret->setCoords(getCoords());
5191   return ret;
5192 }
5193
5194 /*!
5195  * Checks if \a this mesh is constituted by only quadratic cells.
5196  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
5197  *  \throw If the coordinates array is not set.
5198  *  \throw If the nodal connectivity of cells is not defined.
5199  */
5200 bool MEDCouplingUMesh::isFullyQuadratic() const
5201 {
5202   checkFullyDefined();
5203   bool ret=true;
5204   int nbOfCells=getNumberOfCells();
5205   for(int i=0;i<nbOfCells && ret;i++)
5206     {
5207       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5208       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5209       ret=cm.isQuadratic();
5210     }
5211   return ret;
5212 }
5213
5214 /*!
5215  * Checks if \a this mesh includes any quadratic cell.
5216  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5217  *  \throw If the coordinates array is not set.
5218  *  \throw If the nodal connectivity of cells is not defined.
5219  */
5220 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5221 {
5222   checkFullyDefined();
5223   bool ret=false;
5224   int nbOfCells=getNumberOfCells();
5225   for(int i=0;i<nbOfCells && !ret;i++)
5226     {
5227       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5228       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5229       ret=cm.isQuadratic();
5230     }
5231   return ret;
5232 }
5233
5234 /*!
5235  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5236  * this mesh, it remains unchanged.
5237  *  \throw If the coordinates array is not set.
5238  *  \throw If the nodal connectivity of cells is not defined.
5239  */
5240 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5241 {
5242   checkFullyDefined();
5243   int nbOfCells(getNumberOfCells());
5244   int delta=0;
5245   const int *iciptr=_nodal_connec_index->begin();
5246   for(int i=0;i<nbOfCells;i++)
5247     {
5248       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5249       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5250       if(cm.isQuadratic())
5251         {
5252           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5253           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5254           if(!cml.isDynamic())
5255             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5256           else
5257             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5258         }
5259     }
5260   if(delta==0)
5261     return ;
5262   MCAuto<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
5263   const int *icptr(_nodal_connec->begin());
5264   newConn->alloc(getNodalConnectivityArrayLen()-delta,1);
5265   newConnI->alloc(nbOfCells+1,1);
5266   int *ocptr(newConn->getPointer()),*ociptr(newConnI->getPointer());
5267   *ociptr=0;
5268   _types.clear();
5269   for(int i=0;i<nbOfCells;i++,ociptr++)
5270     {
5271       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5272       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5273       if(!cm.isQuadratic())
5274         {
5275           _types.insert(type);
5276           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5277           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5278         }
5279       else
5280         {
5281           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5282           _types.insert(typel);
5283           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5284           int newNbOfNodes=cml.getNumberOfNodes();
5285           if(cml.isDynamic())
5286             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5287           *ocptr++=(int)typel;
5288           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5289           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5290         }
5291     }
5292   setConnectivity(newConn,newConnI,false);
5293 }
5294
5295 /*!
5296  * This method converts all linear cell in \a this to quadratic one.
5297  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5298  * 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)
5299  * 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.
5300  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5301  * end of the existing coordinates.
5302  * 
5303  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5304  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5305  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5306  * 
5307  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5308  *
5309  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5310  */
5311 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5312 {
5313   DataArrayInt *conn=0,*connI=0;
5314   DataArrayDouble *coords=0;
5315   std::set<INTERP_KERNEL::NormalizedCellType> types;
5316   checkFullyDefined();
5317   MCAuto<DataArrayInt> ret,connSafe,connISafe;
5318   MCAuto<DataArrayDouble> coordsSafe;
5319   int meshDim=getMeshDimension();
5320   switch(conversionType)
5321   {
5322     case 0:
5323       switch(meshDim)
5324       {
5325         case 1:
5326           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5327           connSafe=conn; connISafe=connI; coordsSafe=coords;
5328           break;
5329         case 2:
5330           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5331           connSafe=conn; connISafe=connI; coordsSafe=coords;
5332           break;
5333         case 3:
5334           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5335           connSafe=conn; connISafe=connI; coordsSafe=coords;
5336           break;
5337         default:
5338           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5339       }
5340       break;
5341         case 1:
5342           {
5343             switch(meshDim)
5344             {
5345               case 1:
5346                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5347                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5348                 break;
5349               case 2:
5350                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5351                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5352                 break;
5353               case 3:
5354                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5355                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5356                 break;
5357               default:
5358                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5359             }
5360             break;
5361           }
5362         default:
5363           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5364   }
5365   setConnectivity(connSafe,connISafe,false);
5366   _types=types;
5367   setCoords(coordsSafe);
5368   return ret.retn();
5369 }
5370
5371 /*!
5372  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5373  * so that the number of cells remains the same. Quadratic faces are converted to
5374  * polygons. This method works only for 2D meshes in
5375  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5376  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5377  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5378  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5379  *         a polylinized edge constituting the input polygon.
5380  *  \throw If the coordinates array is not set.
5381  *  \throw If the nodal connectivity of cells is not defined.
5382  *  \throw If \a this->getMeshDimension() != 2.
5383  *  \throw If \a this->getSpaceDimension() != 2.
5384  */
5385 void MEDCouplingUMesh::tessellate2D(double eps)
5386 {
5387   int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
5388   if(spaceDim!=2)
5389     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
5390   switch(meshDim)
5391     {
5392     case 1:
5393       return tessellate2DCurveInternal(eps);
5394     case 2:
5395       return tessellate2DInternal(eps);
5396     default:
5397       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
5398     }
5399 }
5400 /*!
5401  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5402  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5403  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5404  *         a sub-divided edge.
5405  *  \throw If the coordinates array is not set.
5406  *  \throw If the nodal connectivity of cells is not defined.
5407  *  \throw If \a this->getMeshDimension() != 1.
5408  *  \throw If \a this->getSpaceDimension() != 2.
5409  */
5410
5411 #if 0
5412 /*!
5413  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5414  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5415  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5416  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5417  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5418  * This method can be seen as the opposite method of colinearize2D.
5419  * 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
5420  * to avoid to modify the numbering of existing nodes.
5421  *
5422  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5423  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5424  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5425  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5426  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5427  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5428  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5429  *
5430  * \sa buildDescendingConnectivity2
5431  */
5432 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5433                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5434 {
5435   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5436     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5437   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5438   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5439     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5440   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5441     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5442   //DataArrayInt *out0(0),*outi0(0);
5443   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5444   //MCAuto<DataArrayInt> out0s(out0),outi0s(outi0);
5445   //out0s=out0s->buildUnique(); out0s->sort(true);
5446 }
5447 #endif
5448
5449 /*!
5450  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5451  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5452  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5453  */
5454 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5455 {
5456   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5457   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5458   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5459   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5460   int nbOfCells=getNumberOfCells();
5461   int nbOfNodes=getNumberOfNodes();
5462   const int *cPtr=_nodal_connec->begin();
5463   const int *icPtr=_nodal_connec_index->begin();
5464   int lastVal=0,offset=nbOfNodes;
5465   for(int i=0;i<nbOfCells;i++,icPtr++)
5466     {
5467       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5468       if(type==INTERP_KERNEL::NORM_SEG2)
5469         {
5470           types.insert(INTERP_KERNEL::NORM_SEG3);
5471           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5472           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5473           newConn->pushBackSilent(offset++);
5474           lastVal+=4;
5475           newConnI->pushBackSilent(lastVal);
5476           ret->pushBackSilent(i);
5477         }
5478       else
5479         {
5480           types.insert(type);
5481           lastVal+=(icPtr[1]-icPtr[0]);
5482           newConnI->pushBackSilent(lastVal);
5483           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5484         }
5485     }
5486   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5487   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5488   return ret.retn();
5489 }
5490
5491 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
5492 {
5493   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5494   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5495   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5496   //
5497   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5498   DataArrayInt *conn1D=0,*conn1DI=0;
5499   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5500   DataArrayDouble *coordsTmp=0;
5501   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5502   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5503   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5504   const int *c1DPtr=conn1D->begin();
5505   const int *c1DIPtr=conn1DI->begin();
5506   int nbOfCells=getNumberOfCells();
5507   const int *cPtr=_nodal_connec->begin();
5508   const int *icPtr=_nodal_connec_index->begin();
5509   int lastVal=0;
5510   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5511     {
5512       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5513       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5514       if(!cm.isQuadratic())
5515         {
5516           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5517           types.insert(typ2); newConn->pushBackSilent(typ2);
5518           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5519           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5520             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5521           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5522           newConnI->pushBackSilent(lastVal);
5523           ret->pushBackSilent(i);
5524         }
5525       else
5526         {
5527           types.insert(typ);
5528           lastVal+=(icPtr[1]-icPtr[0]);
5529           newConnI->pushBackSilent(lastVal);
5530           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5531         }
5532     }
5533   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5534   return ret.retn();
5535 }
5536
5537 /*!
5538  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5539  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5540  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5541  */
5542 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5543 {
5544   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5545   MCAuto<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5546   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5547 }
5548
5549 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5550 {
5551   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5552   MCAuto<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5553   //
5554   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5555   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5556   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5557   //
5558   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5559   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5560   DataArrayInt *conn1D=0,*conn1DI=0;
5561   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5562   DataArrayDouble *coordsTmp=0;
5563   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5564   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5565   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5566   const int *c1DPtr=conn1D->begin();
5567   const int *c1DIPtr=conn1DI->begin();
5568   int nbOfCells=getNumberOfCells();
5569   const int *cPtr=_nodal_connec->begin();
5570   const int *icPtr=_nodal_connec_index->begin();
5571   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5572   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5573     {
5574       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5575       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5576       if(!cm.isQuadratic())
5577         {
5578           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5579           types.insert(typ2); newConn->pushBackSilent(typ2);
5580           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5581           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5582             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5583           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5584           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5585           newConnI->pushBackSilent(lastVal);
5586           ret->pushBackSilent(i);
5587         }
5588       else
5589         {
5590           types.insert(typ);
5591           lastVal+=(icPtr[1]-icPtr[0]);
5592           newConnI->pushBackSilent(lastVal);
5593           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5594         }
5595     }
5596   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5597   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5598   return ret.retn();
5599 }
5600
5601 /*!
5602  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5603  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5604  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5605  */
5606 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5607 {
5608   MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5609   MCAuto<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5610   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5611 }
5612
5613 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5614 {
5615   MCAuto<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5616   MCAuto<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5617   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5618   MCAuto<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5619   //
5620   MCAuto<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5621   MCAuto<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5622   MCAuto<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5623   //
5624   MCAuto<DataArrayDouble> bary=computeCellCenterOfMass();
5625   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5626   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5627   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5628   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5629   MCAuto<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5630   MCAuto<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5631   MCAuto<DataArrayDouble> coordsTmpSafe(coordsTmp);
5632   MCAuto<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5633   MCAuto<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5634   MCAuto<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5635   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5636   int nbOfCells=getNumberOfCells();
5637   const int *cPtr=_nodal_connec->begin();
5638   const int *icPtr=_nodal_connec_index->begin();
5639   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5640   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5641     {
5642       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5643       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5644       if(!cm.isQuadratic())
5645         {
5646           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5647           if(typ2==INTERP_KERNEL::NORM_ERROR)
5648             {
5649               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5650               throw INTERP_KERNEL::Exception(oss.str());
5651             }
5652           types.insert(typ2); newConn->pushBackSilent(typ2);
5653           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5654           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5655             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5656           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5657             {
5658               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5659               int tmpPos=newConn->getNumberOfTuples();
5660               newConn->pushBackSilent(nodeId2);
5661               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5662             }
5663           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5664           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5665           newConnI->pushBackSilent(lastVal);
5666           ret->pushBackSilent(i);
5667         }
5668       else
5669         {
5670           types.insert(typ);
5671           lastVal+=(icPtr[1]-icPtr[0]);
5672           newConnI->pushBackSilent(lastVal);
5673           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5674         }
5675     }
5676   MCAuto<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5677   MCAuto<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5678   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5679   MCAuto<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5680   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5681   int *c=newConn->getPointer();
5682   const int *cI(newConnI->begin());
5683   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5684     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5685   offset=coordsTmp2Safe->getNumberOfTuples();
5686   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5687     c[cI[(*elt)+1]-1]+=offset;
5688   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5689   return ret.retn();
5690 }
5691
5692 /*!
5693  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5694  * In addition, returns an array mapping new cells to old ones. <br>
5695  * This method typically increases the number of cells in \a this mesh
5696  * but the number of nodes remains \b unchanged.
5697  * That's why the 3D splitting policies
5698  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5699  *  \param [in] policy - specifies a pattern used for splitting.
5700  * The semantic of \a policy is:
5701  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5702  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5703  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5704  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5705  *
5706  *
5707  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5708  *          an id of old cell producing it. The caller is to delete this array using
5709  *         decrRef() as it is no more needed.
5710  *
5711  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5712  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5713  *          and \a this->getMeshDimension() != 3. 
5714  *  \throw If \a policy is not one of the four discussed above.
5715  *  \throw If the nodal connectivity of cells is not defined.
5716  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5717  */
5718 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5719 {
5720   switch(policy)
5721   {
5722     case 0:
5723       return simplexizePol0();
5724     case 1:
5725       return simplexizePol1();
5726     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5727         return simplexizePlanarFace5();
5728     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5729         return simplexizePlanarFace6();
5730     default:
5731       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)");
5732   }
5733 }
5734
5735 /*!
5736  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5737  * - 1D: INTERP_KERNEL::NORM_SEG2
5738  * - 2D: INTERP_KERNEL::NORM_TRI3
5739  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5740  *
5741  * This method is useful for users that need to use P1 field services as
5742  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5743  * All these methods need mesh support containing only simplex cells.
5744  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5745  *  \throw If the coordinates array is not set.
5746  *  \throw If the nodal connectivity of cells is not defined.
5747  *  \throw If \a this->getMeshDimension() < 1.
5748  */
5749 bool MEDCouplingUMesh::areOnlySimplexCells() const
5750 {
5751   checkFullyDefined();
5752   int mdim=getMeshDimension();
5753   if(mdim<1 || mdim>3)
5754     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5755   int nbCells=getNumberOfCells();
5756   const int *conn=_nodal_connec->begin();
5757   const int *connI=_nodal_connec_index->begin();
5758   for(int i=0;i<nbCells;i++)
5759     {
5760       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5761       if(!cm.isSimplex())
5762         return false;
5763     }
5764   return true;
5765 }
5766
5767 /*!
5768  * This method implements policy 0 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5769  */
5770 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5771 {
5772   checkConnectivityFullyDefined();
5773   if(getMeshDimension()!=2)
5774     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5775   int nbOfCells=getNumberOfCells();
5776   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5777   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5778   ret->alloc(nbOfCells+nbOfCutCells,1);
5779   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5780   int *retPt=ret->getPointer();
5781   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5782   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5783   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5784   newConn->alloc(getNodalConnectivityArrayLen()+3*nbOfCutCells,1);
5785   int *pt=newConn->getPointer();
5786   int *ptI=newConnI->getPointer();
5787   ptI[0]=0;
5788   const int *oldc=_nodal_connec->begin();
5789   const int *ci=_nodal_connec_index->begin();
5790   for(int i=0;i<nbOfCells;i++,ci++)
5791     {
5792       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5793         {
5794           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5795             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5796           pt=std::copy(tmp,tmp+8,pt);
5797           ptI[1]=ptI[0]+4;
5798           ptI[2]=ptI[0]+8;
5799           *retPt++=i;
5800           *retPt++=i;
5801           ptI+=2;
5802         }
5803       else
5804         {
5805           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5806           ptI[1]=ptI[0]+ci[1]-ci[0];
5807           ptI++;
5808           *retPt++=i;
5809         }
5810     }
5811   _nodal_connec->decrRef();
5812   _nodal_connec=newConn.retn();
5813   _nodal_connec_index->decrRef();
5814   _nodal_connec_index=newConnI.retn();
5815   computeTypes();
5816   updateTime();
5817   return ret.retn();
5818 }
5819
5820 /*!
5821  * This method implements policy 1 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5822  */
5823 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5824 {
5825   checkConnectivityFullyDefined();
5826   if(getMeshDimension()!=2)
5827     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5828   int nbOfCells=getNumberOfCells();
5829   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5830   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5831   ret->alloc(nbOfCells+nbOfCutCells,1);
5832   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5833   int *retPt=ret->getPointer();
5834   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5835   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5836   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5837   newConn->alloc(getNodalConnectivityArrayLen()+3*nbOfCutCells,1);
5838   int *pt=newConn->getPointer();
5839   int *ptI=newConnI->getPointer();
5840   ptI[0]=0;
5841   const int *oldc=_nodal_connec->begin();
5842   const int *ci=_nodal_connec_index->begin();
5843   for(int i=0;i<nbOfCells;i++,ci++)
5844     {
5845       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5846         {
5847           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5848             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5849           pt=std::copy(tmp,tmp+8,pt);
5850           ptI[1]=ptI[0]+4;
5851           ptI[2]=ptI[0]+8;
5852           *retPt++=i;
5853           *retPt++=i;
5854           ptI+=2;
5855         }
5856       else
5857         {
5858           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5859           ptI[1]=ptI[0]+ci[1]-ci[0];
5860           ptI++;
5861           *retPt++=i;
5862         }
5863     }
5864   _nodal_connec->decrRef();
5865   _nodal_connec=newConn.retn();
5866   _nodal_connec_index->decrRef();
5867   _nodal_connec_index=newConnI.retn();
5868   computeTypes();
5869   updateTime();
5870   return ret.retn();
5871 }
5872
5873 /*!
5874  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5875  */
5876 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5877 {
5878   checkConnectivityFullyDefined();
5879   if(getMeshDimension()!=3)
5880     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5881   int nbOfCells=getNumberOfCells();
5882   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5883   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5884   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5885   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5886   int *retPt=ret->getPointer();
5887   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5888   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5889   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5890   newConn->alloc(getNodalConnectivityArrayLen()+16*nbOfCutCells,1);//21
5891   int *pt=newConn->getPointer();
5892   int *ptI=newConnI->getPointer();
5893   ptI[0]=0;
5894   const int *oldc=_nodal_connec->begin();
5895   const int *ci=_nodal_connec_index->begin();
5896   for(int i=0;i<nbOfCells;i++,ci++)
5897     {
5898       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5899         {
5900           for(int j=0;j<5;j++,pt+=5,ptI++)
5901             {
5902               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5903               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];
5904               *retPt++=i;
5905               ptI[1]=ptI[0]+5;
5906             }
5907         }
5908       else
5909         {
5910           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5911           ptI[1]=ptI[0]+ci[1]-ci[0];
5912           ptI++;
5913           *retPt++=i;
5914         }
5915     }
5916   _nodal_connec->decrRef();
5917   _nodal_connec=newConn.retn();
5918   _nodal_connec_index->decrRef();
5919   _nodal_connec_index=newConnI.retn();
5920   computeTypes();
5921   updateTime();
5922   return ret.retn();
5923 }
5924
5925 /*!
5926  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method MEDCoupling::MEDCouplingUMesh::simplexize.
5927  */
5928 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5929 {
5930   checkConnectivityFullyDefined();
5931   if(getMeshDimension()!=3)
5932     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5933   int nbOfCells=getNumberOfCells();
5934   MCAuto<DataArrayInt> ret=DataArrayInt::New();
5935   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5936   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5937   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5938   int *retPt=ret->getPointer();
5939   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
5940   MCAuto<DataArrayInt> newConnI=DataArrayInt::New();
5941   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5942   newConn->alloc(getNodalConnectivityArrayLen()+21*nbOfCutCells,1);
5943   int *pt=newConn->getPointer();
5944   int *ptI=newConnI->getPointer();
5945   ptI[0]=0;
5946   const int *oldc=_nodal_connec->begin();
5947   const int *ci=_nodal_connec_index->begin();
5948   for(int i=0;i<nbOfCells;i++,ci++)
5949     {
5950       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5951         {
5952           for(int j=0;j<6;j++,pt+=5,ptI++)
5953             {
5954               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5955               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];
5956               *retPt++=i;
5957               ptI[1]=ptI[0]+5;
5958             }
5959         }
5960       else
5961         {
5962           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5963           ptI[1]=ptI[0]+ci[1]-ci[0];
5964           ptI++;
5965           *retPt++=i;
5966         }
5967     }
5968   _nodal_connec->decrRef();
5969   _nodal_connec=newConn.retn();
5970   _nodal_connec_index->decrRef();
5971   _nodal_connec_index=newConnI.retn();
5972   computeTypes();
5973   updateTime();
5974   return ret.retn();
5975 }
5976
5977 /*!
5978  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5979  * so that the number of cells remains the same. Quadratic faces are converted to
5980  * polygons. This method works only for 2D meshes in
5981  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5982  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5983  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5984  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5985  *         a polylinized edge constituting the input polygon.
5986  *  \throw If the coordinates array is not set.
5987  *  \throw If the nodal connectivity of cells is not defined.
5988  *  \throw If \a this->getMeshDimension() != 2.
5989  *  \throw If \a this->getSpaceDimension() != 2.
5990  */
5991 void MEDCouplingUMesh::tessellate2DInternal(double eps)
5992 {
5993   checkFullyDefined();
5994   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5995     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DInternal works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5996   double epsa=fabs(eps);
5997   if(epsa<std::numeric_limits<double>::min())
5998     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 !");
5999   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
6000   MCAuto<MEDCouplingUMesh> mDesc(buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
6001   revDesc1=0; revDescIndx1=0;
6002   mDesc->tessellate2D(eps);
6003   subDivide2DMesh(mDesc->_nodal_connec->begin(),mDesc->_nodal_connec_index->begin(),desc1->begin(),descIndx1->begin());
6004   setCoords(mDesc->getCoords());
6005 }
6006
6007 /*!
6008  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
6009  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
6010  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
6011  *         a sub-divided edge.
6012  *  \throw If the coordinates array is not set.
6013  *  \throw If the nodal connectivity of cells is not defined.
6014  *  \throw If \a this->getMeshDimension() != 1.
6015  *  \throw If \a this->getSpaceDimension() != 2.
6016  */
6017 void MEDCouplingUMesh::tessellate2DCurveInternal(double eps)
6018 {
6019   checkFullyDefined();
6020   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
6021     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurveInternal works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
6022   double epsa=fabs(eps);
6023   if(epsa<std::numeric_limits<double>::min())
6024     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 !");
6025   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
6026   int nbCells=getNumberOfCells();
6027   int nbNodes=getNumberOfNodes();
6028   const int *conn=_nodal_connec->begin();
6029   const int *connI=_nodal_connec_index->begin();
6030   const double *coords=_coords->begin();
6031   std::vector<double> addCoo;
6032   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
6033   MCAuto<DataArrayInt> newConnI(DataArrayInt::New());
6034   newConnI->alloc(nbCells+1,1);
6035   int *newConnIPtr=newConnI->getPointer();
6036   *newConnIPtr=0;
6037   int tmp1[3];
6038   INTERP_KERNEL::Node *tmp2[3];
6039   std::set<INTERP_KERNEL::NormalizedCellType> types;
6040   for(int i=0;i<nbCells;i++,newConnIPtr++)
6041     {
6042       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6043       if(cm.isQuadratic())
6044         {//assert(connI[i+1]-connI[i]-1==3)
6045           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
6046           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
6047           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
6048           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
6049           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
6050           if(eac)
6051             {
6052               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
6053               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
6054               delete eac;
6055               newConnIPtr[1]=(int)newConn.size();
6056             }
6057           else
6058             {
6059               types.insert(INTERP_KERNEL::NORM_SEG2);
6060               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
6061               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
6062               newConnIPtr[1]=newConnIPtr[0]+3;
6063             }
6064         }
6065       else
6066         {
6067           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6068           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
6069           newConnIPtr[1]=newConnIPtr[0]+3;
6070         }
6071     }
6072   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
6073     return ;
6074   _types=types;
6075   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
6076   MCAuto<DataArrayInt> newConnArr=DataArrayInt::New();
6077   newConnArr->alloc((int)newConn.size(),1);
6078   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
6079   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
6080   MCAuto<DataArrayDouble> newCoords=DataArrayDouble::New();
6081   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
6082   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
6083   std::copy(addCoo.begin(),addCoo.end(),work);
6084   DataArrayDouble::SetArrayIn(newCoords,_coords);
6085   updateTime();
6086 }
6087
6088 /*!
6089  * 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.
6090  * This method completly ignore coordinates.
6091  * \param nodeSubdived is the nodal connectivity of subdivision of edges
6092  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
6093  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
6094  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
6095  */
6096 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
6097 {
6098   checkFullyDefined();
6099   if(getMeshDimension()!=2)
6100     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
6101   int nbOfCells=getNumberOfCells();
6102   int *connI=_nodal_connec_index->getPointer();
6103   int newConnLgth=0;
6104   for(int i=0;i<nbOfCells;i++,connI++)
6105     {
6106       int offset=descIndex[i];
6107       int nbOfEdges=descIndex[i+1]-offset;
6108       //
6109       bool ddirect=desc[offset+nbOfEdges-1]>0;
6110       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
6111       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
6112       for(int j=0;j<nbOfEdges;j++)
6113         {
6114           bool direct=desc[offset+j]>0;
6115           int edgeId=std::abs(desc[offset+j])-1;
6116           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
6117             {
6118               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
6119               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
6120               int ref2=direct?id1:id2;
6121               if(ref==ref2)
6122                 {
6123                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
6124                   newConnLgth+=nbOfSubNodes-1;
6125                   ref=direct?id2:id1;
6126                 }
6127               else
6128                 {
6129                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
6130                   throw INTERP_KERNEL::Exception(oss.str());
6131                 }
6132             }
6133           else
6134             {
6135               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
6136             }
6137         }
6138       newConnLgth++;//+1 is for cell type
6139       connI[1]=newConnLgth;
6140     }
6141   //
6142   MCAuto<DataArrayInt> newConn=DataArrayInt::New();
6143   newConn->alloc(newConnLgth,1);
6144   int *work=newConn->getPointer();
6145   for(int i=0;i<nbOfCells;i++)
6146     {
6147       *work++=INTERP_KERNEL::NORM_POLYGON;
6148       int offset=descIndex[i];
6149       int nbOfEdges=descIndex[i+1]-offset;
6150       for(int j=0;j<nbOfEdges;j++)
6151         {
6152           bool direct=desc[offset+j]>0;
6153           int edgeId=std::abs(desc[offset+j])-1;
6154           if(direct)
6155             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
6156           else
6157             {
6158               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
6159               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
6160               work=std::copy(it,it+nbOfSubNodes-1,work);
6161             }
6162         }
6163     }
6164   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
6165   _types.clear();
6166   if(nbOfCells>0)
6167     _types.insert(INTERP_KERNEL::NORM_POLYGON);
6168 }
6169
6170 /*!
6171  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
6172  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
6173  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
6174  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
6175  * so it can be useful to call mergeNodes() before calling this method.
6176  *  \throw If \a this->getMeshDimension() <= 1.
6177  *  \throw If the coordinates array is not set.
6178  *  \throw If the nodal connectivity of cells is not defined.
6179  */
6180 void MEDCouplingUMesh::convertDegeneratedCells()
6181 {
6182   checkFullyDefined();
6183   if(getMeshDimension()<=1)
6184     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
6185   int nbOfCells=getNumberOfCells();
6186   if(nbOfCells<1)
6187     return ;
6188   int initMeshLgth=getNodalConnectivityArrayLen();
6189   int *conn=_nodal_connec->getPointer();
6190   int *index=_nodal_connec_index->getPointer();
6191   int posOfCurCell=0;
6192   int newPos=0;
6193   int lgthOfCurCell;
6194   for(int i=0;i<nbOfCells;i++)
6195     {
6196       lgthOfCurCell=index[i+1]-posOfCurCell;
6197       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
6198       int newLgth;
6199       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
6200                                                                                                      conn+newPos+1,newLgth);
6201       conn[newPos]=newType;
6202       newPos+=newLgth+1;
6203       posOfCurCell=index[i+1];
6204       index[i+1]=newPos;
6205     }
6206   if(newPos!=initMeshLgth)
6207     _nodal_connec->reAlloc(newPos);
6208   computeTypes();
6209 }
6210
6211 /*!
6212  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
6213  * A cell is considered to be oriented correctly if an angle between its
6214  * normal vector and a given vector is less than \c PI / \c 2.
6215  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6216  *         cells. 
6217  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6218  *         checked.
6219  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6220  *         is not cleared before filling in.
6221  *  \throw If \a this->getMeshDimension() != 2.
6222  *  \throw If \a this->getSpaceDimension() != 3.
6223  *
6224  *  \if ENABLE_EXAMPLES
6225  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6226  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6227  *  \endif
6228  */
6229 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6230 {
6231   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6232     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6233   int nbOfCells=getNumberOfCells();
6234   const int *conn=_nodal_connec->begin();
6235   const int *connI=_nodal_connec_index->begin();
6236   const double *coordsPtr=_coords->begin();
6237   for(int i=0;i<nbOfCells;i++)
6238     {
6239       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6240       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6241         {
6242           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6243           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6244             cells.push_back(i);
6245         }
6246     }
6247 }
6248
6249 /*!
6250  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6251  * considered to be oriented correctly if an angle between its normal vector and a
6252  * given vector is less than \c PI / \c 2. 
6253  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6254  *         cells. 
6255  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6256  *         checked.
6257  *  \throw If \a this->getMeshDimension() != 2.
6258  *  \throw If \a this->getSpaceDimension() != 3.
6259  *
6260  *  \if ENABLE_EXAMPLES
6261  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6262  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6263  *  \endif
6264  *
6265  *  \sa changeOrientationOfCells
6266  */
6267 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6268 {
6269   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6270     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6271   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6272   const int *connI(_nodal_connec_index->begin());
6273   const double *coordsPtr(_coords->begin());
6274   bool isModified(false);
6275   for(int i=0;i<nbOfCells;i++)
6276     {
6277       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6278       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6279         {
6280           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6281           bool isQuadratic(cm.isQuadratic());
6282           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6283             {
6284               isModified=true;
6285               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6286             }
6287         }
6288     }
6289   if(isModified)
6290     _nodal_connec->declareAsNew();
6291   updateTime();
6292 }
6293
6294 /*!
6295  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6296  *
6297  * \sa orientCorrectly2DCells
6298  */
6299 void MEDCouplingUMesh::changeOrientationOfCells()
6300 {
6301   int mdim(getMeshDimension());
6302   if(mdim!=2 && mdim!=1)
6303     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6304   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6305   const int *connI(_nodal_connec_index->begin());
6306   if(mdim==2)
6307     {//2D
6308       for(int i=0;i<nbOfCells;i++)
6309         {
6310           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6311           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6312           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6313         }
6314     }
6315   else
6316     {//1D
6317       for(int i=0;i<nbOfCells;i++)
6318         {
6319           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6320           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6321           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6322         }
6323     }
6324 }
6325
6326 /*!
6327  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6328  * oriented facets. The normal vector of the facet should point out of the cell.
6329  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6330  *         is not cleared before filling in.
6331  *  \throw If \a this->getMeshDimension() != 3.
6332  *  \throw If \a this->getSpaceDimension() != 3.
6333  *  \throw If the coordinates array is not set.
6334  *  \throw If the nodal connectivity of cells is not defined.
6335  *
6336  *  \if ENABLE_EXAMPLES
6337  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6338  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6339  *  \endif
6340  */
6341 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6342 {
6343   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6344     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6345   int nbOfCells=getNumberOfCells();
6346   const int *conn=_nodal_connec->begin();
6347   const int *connI=_nodal_connec_index->begin();
6348   const double *coordsPtr=_coords->begin();
6349   for(int i=0;i<nbOfCells;i++)
6350     {
6351       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6352       if(type==INTERP_KERNEL::NORM_POLYHED)
6353         {
6354           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6355             cells.push_back(i);
6356         }
6357     }
6358 }
6359
6360 /*!
6361  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6362  * out of the cell. 
6363  *  \throw If \a this->getMeshDimension() != 3.
6364  *  \throw If \a this->getSpaceDimension() != 3.
6365  *  \throw If the coordinates array is not set.
6366  *  \throw If the nodal connectivity of cells is not defined.
6367  *  \throw If the reparation fails.
6368  *
6369  *  \if ENABLE_EXAMPLES
6370  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6371  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6372  *  \endif
6373  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6374  */
6375 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6376 {
6377   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6378     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6379   int nbOfCells=getNumberOfCells();
6380   int *conn=_nodal_connec->getPointer();
6381   const int *connI=_nodal_connec_index->begin();
6382   const double *coordsPtr=_coords->begin();
6383   for(int i=0;i<nbOfCells;i++)
6384     {
6385       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6386       if(type==INTERP_KERNEL::NORM_POLYHED)
6387         {
6388           try
6389           {
6390               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6391                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6392           }
6393           catch(INTERP_KERNEL::Exception& e)
6394           {
6395               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6396               throw INTERP_KERNEL::Exception(oss.str());
6397           }
6398         }
6399     }
6400   updateTime();
6401 }
6402
6403 /*!
6404  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6405  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6406  * according to which the first facet of the cell should be oriented to have the normal vector
6407  * pointing out of cell.
6408  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6409  *         cells. The caller is to delete this array using decrRef() as it is no more
6410  *         needed. 
6411  *  \throw If \a this->getMeshDimension() != 3.
6412  *  \throw If \a this->getSpaceDimension() != 3.
6413  *  \throw If the coordinates array is not set.
6414  *  \throw If the nodal connectivity of cells is not defined.
6415  *
6416  *  \if ENABLE_EXAMPLES
6417  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6418  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6419  *  \endif
6420  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6421  */
6422 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6423 {
6424   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6425   if(getMeshDimension()!=3)
6426     throw INTERP_KERNEL::Exception(msg);
6427   int spaceDim=getSpaceDimension();
6428   if(spaceDim!=3)
6429     throw INTERP_KERNEL::Exception(msg);
6430   //
6431   int nbOfCells=getNumberOfCells();
6432   int *conn=_nodal_connec->getPointer();
6433   const int *connI=_nodal_connec_index->begin();
6434   const double *coo=getCoords()->begin();
6435   MCAuto<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6436   for(int i=0;i<nbOfCells;i++)
6437     {
6438       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6439       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6440         {
6441           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6442             {
6443               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6444               cells->pushBackSilent(i);
6445             }
6446         }
6447     }
6448   return cells.retn();
6449 }
6450
6451 /*!
6452  * This method is a faster method to correct orientation of all 3D cells in \a this.
6453  * 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.
6454  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkConsistency should throw no exception.
6455  * 
6456  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6457  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6458  */
6459 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6460 {
6461   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6462     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6463   int nbOfCells=getNumberOfCells();
6464   int *conn=_nodal_connec->getPointer();
6465   const int *connI=_nodal_connec_index->begin();
6466   const double *coordsPtr=_coords->begin();
6467   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6468   for(int i=0;i<nbOfCells;i++)
6469     {
6470       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6471       switch(type)
6472       {
6473         case INTERP_KERNEL::NORM_TETRA4:
6474           {
6475             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6476               {
6477                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6478                 ret->pushBackSilent(i);
6479               }
6480             break;
6481           }
6482         case INTERP_KERNEL::NORM_PYRA5:
6483           {
6484             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6485               {
6486                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6487                 ret->pushBackSilent(i);
6488               }
6489             break;
6490           }
6491         case INTERP_KERNEL::NORM_PENTA6:
6492         case INTERP_KERNEL::NORM_HEXA8:
6493         case INTERP_KERNEL::NORM_HEXGP12:
6494           {
6495             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6496               {
6497                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6498                 ret->pushBackSilent(i);
6499               }
6500             break;
6501           }
6502         case INTERP_KERNEL::NORM_POLYHED:
6503           {
6504             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6505               {
6506                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6507                 ret->pushBackSilent(i);
6508               }
6509             break;
6510           }
6511         default:
6512           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 !");
6513       }
6514     }
6515   updateTime();
6516   return ret.retn();
6517 }
6518
6519 /*!
6520  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6521  * If it is not the case an exception will be thrown.
6522  * This method is fast because the first cell of \a this is used to compute the plane.
6523  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6524  * \param pos output of size at least 3 used to store a point owned of searched plane.
6525  */
6526 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6527 {
6528   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6529     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6530   const int *conn=_nodal_connec->begin();
6531   const int *connI=_nodal_connec_index->begin();
6532   const double *coordsPtr=_coords->begin();
6533   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6534   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6535 }
6536
6537 /*!
6538  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6539  * cells. Currently cells of the following types are treated:
6540  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6541  * For a cell of other type an exception is thrown.
6542  * Space dimension of a 2D mesh can be either 2 or 3.
6543  * The Edge Ratio of a cell \f$t\f$ is: 
6544  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6545  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6546  *  the smallest edge lengths of \f$t\f$.
6547  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6548  *          cells and one time, lying on \a this mesh. The caller is to delete this
6549  *          field using decrRef() as it is no more needed. 
6550  *  \throw If the coordinates array is not set.
6551  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6552  *  \throw If the connectivity data array has more than one component.
6553  *  \throw If the connectivity data array has a named component.
6554  *  \throw If the connectivity index data array has more than one component.
6555  *  \throw If the connectivity index data array has a named component.
6556  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6557  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6558  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6559  */
6560 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6561 {
6562   checkConsistencyLight();
6563   int spaceDim=getSpaceDimension();
6564   int meshDim=getMeshDimension();
6565   if(spaceDim!=2 && spaceDim!=3)
6566     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6567   if(meshDim!=2 && meshDim!=3)
6568     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6569   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6570   ret->setMesh(this);
6571   int nbOfCells=getNumberOfCells();
6572   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6573   arr->alloc(nbOfCells,1);
6574   double *pt=arr->getPointer();
6575   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6576   const int *conn=_nodal_connec->begin();
6577   const int *connI=_nodal_connec_index->begin();
6578   const double *coo=_coords->begin();
6579   double tmp[12];
6580   for(int i=0;i<nbOfCells;i++,pt++)
6581     {
6582       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6583       switch(t)
6584       {
6585         case INTERP_KERNEL::NORM_TRI3:
6586           {
6587             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6588             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6589             break;
6590           }
6591         case INTERP_KERNEL::NORM_QUAD4:
6592           {
6593             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6594             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6595             break;
6596           }
6597         case INTERP_KERNEL::NORM_TETRA4:
6598           {
6599             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6600             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6601             break;
6602           }
6603         default:
6604           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6605       }
6606       conn+=connI[i+1]-connI[i];
6607     }
6608   ret->setName("EdgeRatio");
6609   ret->synchronizeTimeWithSupport();
6610   return ret.retn();
6611 }
6612
6613 /*!
6614  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6615  * cells. Currently cells of the following types are treated:
6616  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6617  * For a cell of other type an exception is thrown.
6618  * Space dimension of a 2D mesh can be either 2 or 3.
6619  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6620  *          cells and one time, lying on \a this mesh. The caller is to delete this
6621  *          field using decrRef() as it is no more needed. 
6622  *  \throw If the coordinates array is not set.
6623  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6624  *  \throw If the connectivity data array has more than one component.
6625  *  \throw If the connectivity data array has a named component.
6626  *  \throw If the connectivity index data array has more than one component.
6627  *  \throw If the connectivity index data array has a named component.
6628  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6629  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6630  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6631  */
6632 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6633 {
6634   checkConsistencyLight();
6635   int spaceDim=getSpaceDimension();
6636   int meshDim=getMeshDimension();
6637   if(spaceDim!=2 && spaceDim!=3)
6638     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6639   if(meshDim!=2 && meshDim!=3)
6640     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6641   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6642   ret->setMesh(this);
6643   int nbOfCells=getNumberOfCells();
6644   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6645   arr->alloc(nbOfCells,1);
6646   double *pt=arr->getPointer();
6647   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6648   const int *conn=_nodal_connec->begin();
6649   const int *connI=_nodal_connec_index->begin();
6650   const double *coo=_coords->begin();
6651   double tmp[12];
6652   for(int i=0;i<nbOfCells;i++,pt++)
6653     {
6654       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6655       switch(t)
6656       {
6657         case INTERP_KERNEL::NORM_TRI3:
6658           {
6659             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6660             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6661             break;
6662           }
6663         case INTERP_KERNEL::NORM_QUAD4:
6664           {
6665             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6666             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6667             break;
6668           }
6669         case INTERP_KERNEL::NORM_TETRA4:
6670           {
6671             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6672             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6673             break;
6674           }
6675         default:
6676           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6677       }
6678       conn+=connI[i+1]-connI[i];
6679     }
6680   ret->setName("AspectRatio");
6681   ret->synchronizeTimeWithSupport();
6682   return ret.retn();
6683 }
6684
6685 /*!
6686  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6687  * cells of \a this 2D mesh in 3D space. It is a measure of the "planarity" of 2D cell
6688  * in 3D space. Currently only cells of the following types are
6689  * treated: INTERP_KERNEL::NORM_QUAD4.
6690  * For a cell of other type an exception is thrown.
6691  * The warp field is computed as follows: let (a,b,c,d) be the points of the quad.
6692  * Defining
6693  * \f$t=\vec{da}\times\vec{ab}\f$,
6694  * \f$u=\vec{ab}\times\vec{bc}\f$
6695  * \f$v=\vec{bc}\times\vec{cd}\f$
6696  * \f$w=\vec{cd}\times\vec{da}\f$, the warp is defined as \f$W^3\f$ with
6697  *  \f[
6698  *     W=min(\frac{t}{|t|}\cdot\frac{v}{|v|}, \frac{u}{|u|}\cdot\frac{w}{|w|})
6699  *  \f]
6700  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6701  *          cells and one time, lying on \a this mesh. The caller is to delete this
6702  *          field using decrRef() as it is no more needed. 
6703  *  \throw If the coordinates array is not set.
6704  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6705  *  \throw If the connectivity data array has more than one component.
6706  *  \throw If the connectivity data array has a named component.
6707  *  \throw If the connectivity index data array has more than one component.
6708  *  \throw If the connectivity index data array has a named component.
6709  *  \throw If \a this->getMeshDimension() != 2.
6710  *  \throw If \a this->getSpaceDimension() != 3.
6711  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6712  */
6713 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6714 {
6715   checkConsistencyLight();
6716   int spaceDim=getSpaceDimension();
6717   int meshDim=getMeshDimension();
6718   if(spaceDim!=3)
6719     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6720   if(meshDim!=2)
6721     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6722   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6723   ret->setMesh(this);
6724   int nbOfCells=getNumberOfCells();
6725   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6726   arr->alloc(nbOfCells,1);
6727   double *pt=arr->getPointer();
6728   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6729   const int *conn=_nodal_connec->begin();
6730   const int *connI=_nodal_connec_index->begin();
6731   const double *coo=_coords->begin();
6732   double tmp[12];
6733   for(int i=0;i<nbOfCells;i++,pt++)
6734     {
6735       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6736       switch(t)
6737       {
6738         case INTERP_KERNEL::NORM_QUAD4:
6739           {
6740             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6741             *pt=INTERP_KERNEL::quadWarp(tmp);
6742             break;
6743           }
6744         default:
6745           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6746       }
6747       conn+=connI[i+1]-connI[i];
6748     }
6749   ret->setName("Warp");
6750   ret->synchronizeTimeWithSupport();
6751   return ret.retn();
6752 }
6753
6754
6755 /*!
6756  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6757  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6758  * treated: INTERP_KERNEL::NORM_QUAD4.
6759  * The skew is computed as follow for a quad with points (a,b,c,d): let
6760  * \f$u=\vec{ab}+\vec{dc}\f$ and \f$v=\vec{ac}+\vec{bd}\f$
6761  * then the skew is computed as:
6762  *  \f[
6763  *    s=\frac{u}{|u|}\cdot\frac{v}{|v|}
6764  *  \f]
6765  *
6766  * For a cell of other type an exception is thrown.
6767  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6768  *          cells and one time, lying on \a this mesh. The caller is to delete this
6769  *          field using decrRef() as it is no more needed. 
6770  *  \throw If the coordinates array is not set.
6771  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6772  *  \throw If the connectivity data array has more than one component.
6773  *  \throw If the connectivity data array has a named component.
6774  *  \throw If the connectivity index data array has more than one component.
6775  *  \throw If the connectivity index data array has a named component.
6776  *  \throw If \a this->getMeshDimension() != 2.
6777  *  \throw If \a this->getSpaceDimension() != 3.
6778  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6779  */
6780 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6781 {
6782   checkConsistencyLight();
6783   int spaceDim=getSpaceDimension();
6784   int meshDim=getMeshDimension();
6785   if(spaceDim!=3)
6786     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6787   if(meshDim!=2)
6788     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6789   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6790   ret->setMesh(this);
6791   int nbOfCells=getNumberOfCells();
6792   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
6793   arr->alloc(nbOfCells,1);
6794   double *pt=arr->getPointer();
6795   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6796   const int *conn=_nodal_connec->begin();
6797   const int *connI=_nodal_connec_index->begin();
6798   const double *coo=_coords->begin();
6799   double tmp[12];
6800   for(int i=0;i<nbOfCells;i++,pt++)
6801     {
6802       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6803       switch(t)
6804       {
6805         case INTERP_KERNEL::NORM_QUAD4:
6806           {
6807             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6808             *pt=INTERP_KERNEL::quadSkew(tmp);
6809             break;
6810           }
6811         default:
6812           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6813       }
6814       conn+=connI[i+1]-connI[i];
6815     }
6816   ret->setName("Skew");
6817   ret->synchronizeTimeWithSupport();
6818   return ret.retn();
6819 }
6820
6821 /*!
6822  * 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.
6823  *
6824  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6825  *
6826  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6827  */
6828 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6829 {
6830   checkConsistencyLight();
6831   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6832   ret->setMesh(this);
6833   std::set<INTERP_KERNEL::NormalizedCellType> types;
6834   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6835   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6836   MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
6837   arr->alloc(nbCells,1);
6838   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6839     {
6840       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6841       MCAuto<DataArrayInt> cellIds(giveCellsWithType(*it));
6842       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6843     }
6844   ret->setArray(arr);
6845   ret->setName("Diameter");
6846   return ret.retn();
6847 }
6848
6849 /*!
6850  * This method aggregate the bbox of each cell and put it into bbox parameter (xmin,xmax,ymin,ymax,zmin,zmax).
6851  * 
6852  * \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)
6853  *                         For all other cases this input parameter is ignored.
6854  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6855  * 
6856  * \throw If \a this is not fully set (coordinates and connectivity).
6857  * \throw If a cell in \a this has no valid nodeId.
6858  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6859  */
6860 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6861 {
6862   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6863   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.
6864     return getBoundingBoxForBBTreeFast();
6865   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6866     {
6867       bool presenceOfQuadratic(false);
6868       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6869         {
6870           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6871           if(cm.isQuadratic())
6872             presenceOfQuadratic=true;
6873         }
6874       if(!presenceOfQuadratic)
6875         return getBoundingBoxForBBTreeFast();
6876       if(mDim==2 && sDim==2)
6877         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6878       else
6879         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6880     }
6881   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) !");
6882 }
6883
6884 /*!
6885  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6886  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6887  * 
6888  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6889  * 
6890  * \throw If \a this is not fully set (coordinates and connectivity).
6891  * \throw If a cell in \a this has no valid nodeId.
6892  */
6893 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6894 {
6895   checkFullyDefined();
6896   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6897   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6898   double *bbox(ret->getPointer());
6899   for(int i=0;i<nbOfCells*spaceDim;i++)
6900     {
6901       bbox[2*i]=std::numeric_limits<double>::max();
6902       bbox[2*i+1]=-std::numeric_limits<double>::max();
6903     }
6904   const double *coordsPtr(_coords->begin());
6905   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
6906   for(int i=0;i<nbOfCells;i++)
6907     {
6908       int offset=connI[i]+1;
6909       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6910       for(int j=0;j<nbOfNodesForCell;j++)
6911         {
6912           int nodeId=conn[offset+j];
6913           if(nodeId>=0 && nodeId<nbOfNodes)
6914             {
6915               for(int k=0;k<spaceDim;k++)
6916                 {
6917                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6918                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6919                 }
6920               kk++;
6921             }
6922         }
6923       if(kk==0)
6924         {
6925           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6926           throw INTERP_KERNEL::Exception(oss.str());
6927         }
6928     }
6929   return ret.retn();
6930 }
6931
6932 /*!
6933  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6934  * useful for 2D meshes having quadratic cells
6935  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6936  * the two extremities of the arc of circle).
6937  * 
6938  * \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)
6939  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6940  * \throw If \a this is not fully defined.
6941  * \throw If \a this is not a mesh with meshDimension equal to 2.
6942  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6943  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6944  */
6945 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6946 {
6947   checkFullyDefined();
6948   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6949   if(spaceDim!=2 || mDim!=2)
6950     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!");
6951   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6952   double *bbox(ret->getPointer());
6953   const double *coords(_coords->begin());
6954   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
6955   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6956     {
6957       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6958       int sz(connI[1]-connI[0]-1);
6959       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6960       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6961       INTERP_KERNEL::QuadraticPolygon *pol(0);
6962       for(int j=0;j<sz;j++)
6963         {
6964           int nodeId(conn[*connI+1+j]);
6965           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6966         }
6967       if(!cm.isQuadratic())
6968         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6969       else
6970         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6971       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6972       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6973     }
6974   return ret.retn();
6975 }
6976
6977 /*!
6978  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6979  * useful for 2D meshes having quadratic cells
6980  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6981  * the two extremities of the arc of circle).
6982  * 
6983  * \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)
6984  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6985  * \throw If \a this is not fully defined.
6986  * \throw If \a this is not a mesh with meshDimension equal to 1.
6987  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6988  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6989  */
6990 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6991 {
6992   checkFullyDefined();
6993   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6994   if(spaceDim!=2 || mDim!=1)
6995     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!");
6996   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6997   double *bbox(ret->getPointer());
6998   const double *coords(_coords->begin());
6999   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
7000   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
7001     {
7002       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
7003       int sz(connI[1]-connI[0]-1);
7004       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
7005       std::vector<INTERP_KERNEL::Node *> nodes(sz);
7006       INTERP_KERNEL::Edge *edge(0);
7007       for(int j=0;j<sz;j++)
7008         {
7009           int nodeId(conn[*connI+1+j]);
7010           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
7011         }
7012       if(!cm.isQuadratic())
7013         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
7014       else
7015         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
7016       const INTERP_KERNEL::Bounds& b(edge->getBounds());
7017       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
7018     }
7019   return ret.retn();
7020 }
7021
7022 /// @cond INTERNAL
7023
7024 namespace MEDCouplingImpl
7025 {
7026   class ConnReader
7027   {
7028   public:
7029     ConnReader(const int *c, int val):_conn(c),_val(val) { }
7030     bool operator() (const int& pos) { return _conn[pos]!=_val; }
7031   private:
7032     const int *_conn;
7033     int _val;
7034   };
7035
7036   class ConnReader2
7037   {
7038   public:
7039     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
7040     bool operator() (const int& pos) { return _conn[pos]==_val; }
7041   private:
7042     const int *_conn;
7043     int _val;
7044   };
7045 }
7046
7047 /// @endcond
7048
7049 /*!
7050  * This method expects that \a this is sorted by types. If not an exception will be thrown.
7051  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
7052  * \a this is composed in cell types.
7053  * The returned array is of size 3*n where n is the number of different types present in \a this. 
7054  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
7055  * This parameter is kept only for compatibility with other methode listed above.
7056  */
7057 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
7058 {
7059   checkConnectivityFullyDefined();
7060   const int *conn=_nodal_connec->begin();
7061   const int *connI=_nodal_connec_index->begin();
7062   const int *work=connI;
7063   int nbOfCells=getNumberOfCells();
7064   std::size_t n=getAllGeoTypes().size();
7065   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
7066   std::set<INTERP_KERNEL::NormalizedCellType> types;
7067   for(std::size_t i=0;work!=connI+nbOfCells;i++)
7068     {
7069       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
7070       if(types.find(typ)!=types.end())
7071         {
7072           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
7073           oss << " is not contiguous !";
7074           throw INTERP_KERNEL::Exception(oss.str());
7075         }
7076       types.insert(typ);
7077       ret[3*i]=typ;
7078       const int *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ));
7079       ret[3*i+1]=(int)std::distance(work,work2);
7080       work=work2;
7081     }
7082   return ret;
7083 }
7084
7085 /*!
7086  * This method is used to check that this has contiguous cell type in same order than described in \a code.
7087  * only for types cell, type node is not managed.
7088  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
7089  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
7090  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
7091  * If 2 or more same geometric type is in \a code and exception is thrown too.
7092  *
7093  * This method firstly checks
7094  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
7095  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
7096  * an exception is thrown too.
7097  * 
7098  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
7099  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
7100  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
7101  */
7102 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
7103 {
7104   if(code.empty())
7105     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
7106   std::size_t sz=code.size();
7107   std::size_t n=sz/3;
7108   if(sz%3!=0)
7109     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
7110   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7111   int nb=0;
7112   bool isNoPflUsed=true;
7113   for(std::size_t i=0;i<n;i++)
7114     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
7115       {
7116         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
7117         nb+=code[3*i+1];
7118         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
7119           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
7120         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
7121       }
7122   if(types.size()!=n)
7123     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
7124   if(isNoPflUsed)
7125     {
7126       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
7127         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
7128       if(types.size()==_types.size())
7129         return 0;
7130     }
7131   MCAuto<DataArrayInt> ret=DataArrayInt::New();
7132   ret->alloc(nb,1);
7133   int *retPtr=ret->getPointer();
7134   const int *connI=_nodal_connec_index->begin();
7135   const int *conn=_nodal_connec->begin();
7136   int nbOfCells=getNumberOfCells();
7137   const int *i=connI;
7138   int kk=0;
7139   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
7140     {
7141       i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,(int)(*it)));
7142       int offset=(int)std::distance(connI,i);
7143       const int *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)(*it)));
7144       int nbOfCellsOfCurType=(int)std::distance(i,j);
7145       if(code[3*kk+2]==-1)
7146         for(int k=0;k<nbOfCellsOfCurType;k++)
7147           *retPtr++=k+offset;
7148       else
7149         {
7150           int idInIdsPerType=code[3*kk+2];
7151           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
7152             {
7153               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
7154               if(zePfl)
7155                 {
7156                   zePfl->checkAllocated();
7157                   if(zePfl->getNumberOfComponents()==1)
7158                     {
7159                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
7160                         {
7161                           if(*k>=0 && *k<nbOfCellsOfCurType)
7162                             *retPtr=(*k)+offset;
7163                           else
7164                             {
7165                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
7166                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
7167                               throw INTERP_KERNEL::Exception(oss.str());
7168                             }
7169                         }
7170                     }
7171                   else
7172                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
7173                 }
7174               else
7175                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
7176             }
7177           else
7178             {
7179               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
7180               oss << " should be in [0," << idsPerType.size() << ") !";
7181               throw INTERP_KERNEL::Exception(oss.str());
7182             }
7183         }
7184       i=j;
7185     }
7186   return ret.retn();
7187 }
7188
7189 /*!
7190  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
7191  * 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.
7192  * 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.
7193  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
7194  * 
7195  * \param [in] profile
7196  * \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.
7197  * \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,
7198  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
7199  * \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.
7200  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
7201  * \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
7202  */
7203 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
7204 {
7205   if(!profile)
7206     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
7207   if(profile->getNumberOfComponents()!=1)
7208     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
7209   checkConnectivityFullyDefined();
7210   const int *conn=_nodal_connec->begin();
7211   const int *connI=_nodal_connec_index->begin();
7212   int nbOfCells=getNumberOfCells();
7213   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7214   std::vector<int> typeRangeVals(1);
7215   for(const int *i=connI;i!=connI+nbOfCells;)
7216     {
7217       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7218       if(std::find(types.begin(),types.end(),curType)!=types.end())
7219         {
7220           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
7221         }
7222       types.push_back(curType);
7223       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7224       typeRangeVals.push_back((int)std::distance(connI,i));
7225     }
7226   //
7227   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
7228   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
7229   MCAuto<DataArrayInt> tmp0=castArr;
7230   MCAuto<DataArrayInt> tmp1=rankInsideCast;
7231   MCAuto<DataArrayInt> tmp2=castsPresent;
7232   //
7233   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
7234   code.resize(3*nbOfCastsFinal);
7235   std::vector< MCAuto<DataArrayInt> > idsInPflPerType2;
7236   std::vector< MCAuto<DataArrayInt> > idsPerType2;
7237   for(int i=0;i<nbOfCastsFinal;i++)
7238     {
7239       int castId=castsPresent->getIJ(i,0);
7240       MCAuto<DataArrayInt> tmp3=castArr->findIdsEqual(castId);
7241       idsInPflPerType2.push_back(tmp3);
7242       code[3*i]=(int)types[castId];
7243       code[3*i+1]=tmp3->getNumberOfTuples();
7244       MCAuto<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->begin(),tmp3->begin()+tmp3->getNumberOfTuples());
7245       if(!tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
7246         {
7247           tmp4->copyStringInfoFrom(*profile);
7248           idsPerType2.push_back(tmp4);
7249           code[3*i+2]=(int)idsPerType2.size()-1;
7250         }
7251       else
7252         {
7253           code[3*i+2]=-1;
7254         }
7255     }
7256   std::size_t sz2=idsInPflPerType2.size();
7257   idsInPflPerType.resize(sz2);
7258   for(std::size_t i=0;i<sz2;i++)
7259     {
7260       DataArrayInt *locDa=idsInPflPerType2[i];
7261       locDa->incrRef();
7262       idsInPflPerType[i]=locDa;
7263     }
7264   std::size_t sz=idsPerType2.size();
7265   idsPerType.resize(sz);
7266   for(std::size_t i=0;i<sz;i++)
7267     {
7268       DataArrayInt *locDa=idsPerType2[i];
7269       locDa->incrRef();
7270       idsPerType[i]=locDa;
7271     }
7272 }
7273
7274 /*!
7275  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7276  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7277  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7278  * 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.
7279  */
7280 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7281 {
7282   checkFullyDefined();
7283   nM1LevMesh->checkFullyDefined();
7284   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7285     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7286   if(_coords!=nM1LevMesh->getCoords())
7287     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7288   MCAuto<DataArrayInt> tmp0=DataArrayInt::New();
7289   MCAuto<DataArrayInt> tmp1=DataArrayInt::New();
7290   MCAuto<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7291   MCAuto<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7292   desc->transformWithIndArr(ret0->begin(),ret0->begin()+ret0->getNbOfElems());
7293   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7294   tmp->setConnectivity(tmp0,tmp1);
7295   tmp->renumberCells(ret0->begin(),false);
7296   revDesc=tmp->getNodalConnectivity();
7297   revDescIndx=tmp->getNodalConnectivityIndex();
7298   DataArrayInt *ret=0;
7299   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7300     {
7301       int tmp2;
7302       ret->getMaxValue(tmp2);
7303       ret->decrRef();
7304       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7305       throw INTERP_KERNEL::Exception(oss.str());
7306     }
7307   nM1LevMeshIds=ret;
7308   //
7309   revDesc->incrRef();
7310   revDescIndx->incrRef();
7311   ret1->incrRef();
7312   ret0->incrRef();
7313   meshnM1Old2New=ret0;
7314   return ret1;
7315 }
7316
7317 /*!
7318  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7319  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7320  * in "Old to New" mode.
7321  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7322  *          this array using decrRef() as it is no more needed.
7323  *  \throw If the nodal connectivity of cells is not defined.
7324  */
7325 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7326 {
7327   checkConnectivityFullyDefined();
7328   MCAuto<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7329   renumberCells(ret->begin(),false);
7330   return ret.retn();
7331 }
7332
7333 /*!
7334  * This methods checks that cells are sorted by their types.
7335  * This method makes asumption (no check) that connectivity is correctly set before calling.
7336  */
7337 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7338 {
7339   checkFullyDefined();
7340   const int *conn=_nodal_connec->begin();
7341   const int *connI=_nodal_connec_index->begin();
7342   int nbOfCells=getNumberOfCells();
7343   std::set<INTERP_KERNEL::NormalizedCellType> types;
7344   for(const int *i=connI;i!=connI+nbOfCells;)
7345     {
7346       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7347       if(types.find(curType)!=types.end())
7348         return false;
7349       types.insert(curType);
7350       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7351     }
7352   return true;
7353 }
7354
7355 /*!
7356  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7357  * The geometric type order is specified by MED file.
7358  * 
7359  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7360  */
7361 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7362 {
7363   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7364 }
7365
7366 /*!
7367  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7368  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7369  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7370  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7371  */
7372 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7373 {
7374   checkFullyDefined();
7375   const int *conn=_nodal_connec->begin();
7376   const int *connI=_nodal_connec_index->begin();
7377   int nbOfCells=getNumberOfCells();
7378   if(nbOfCells==0)
7379     return true;
7380   int lastPos=-1;
7381   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7382   for(const int *i=connI;i!=connI+nbOfCells;)
7383     {
7384       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7385       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7386       if(isTypeExists!=orderEnd)
7387         {
7388           int pos=(int)std::distance(orderBg,isTypeExists);
7389           if(pos<=lastPos)
7390             return false;
7391           lastPos=pos;
7392           i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7393         }
7394       else
7395         {
7396           if(sg.find(curType)==sg.end())
7397             {
7398               i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7399               sg.insert(curType);
7400             }
7401           else
7402             return false;
7403         }
7404     }
7405   return true;
7406 }
7407
7408 /*!
7409  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7410  * 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
7411  * 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'.
7412  */
7413 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7414 {
7415   checkConnectivityFullyDefined();
7416   int nbOfCells=getNumberOfCells();
7417   const int *conn=_nodal_connec->begin();
7418   const int *connI=_nodal_connec_index->begin();
7419   MCAuto<DataArrayInt> tmpa=DataArrayInt::New();
7420   MCAuto<DataArrayInt> tmpb=DataArrayInt::New();
7421   tmpa->alloc(nbOfCells,1);
7422   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7423   tmpb->fillWithZero();
7424   int *tmp=tmpa->getPointer();
7425   int *tmp2=tmpb->getPointer();
7426   for(const int *i=connI;i!=connI+nbOfCells;i++)
7427     {
7428       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7429       if(where!=orderEnd)
7430         {
7431           int pos=(int)std::distance(orderBg,where);
7432           tmp2[pos]++;
7433           tmp[std::distance(connI,i)]=pos;
7434         }
7435       else
7436         {
7437           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7438           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7439           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7440           throw INTERP_KERNEL::Exception(oss.str());
7441         }
7442     }
7443   nbPerType=tmpb.retn();
7444   return tmpa.retn();
7445 }
7446
7447 /*!
7448  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7449  *
7450  * \return a new object containing the old to new correspondance.
7451  *
7452  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7453  */
7454 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7455 {
7456   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7457 }
7458
7459 /*!
7460  * 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.
7461  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7462  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7463  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7464  */
7465 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7466 {
7467   DataArrayInt *nbPerType=0;
7468   MCAuto<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7469   nbPerType->decrRef();
7470   return tmpa->buildPermArrPerLevel();
7471 }
7472
7473 /*!
7474  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7475  * The number of cells remains unchanged after the call of this method.
7476  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7477  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7478  *
7479  * \return the array giving the correspondance old to new.
7480  */
7481 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7482 {
7483   checkFullyDefined();
7484   computeTypes();
7485   const int *conn=_nodal_connec->begin();
7486   const int *connI=_nodal_connec_index->begin();
7487   int nbOfCells=getNumberOfCells();
7488   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7489   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7490     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7491       {
7492         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7493         types.push_back(curType);
7494         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7495       }
7496   DataArrayInt *ret=DataArrayInt::New();
7497   ret->alloc(nbOfCells,1);
7498   int *retPtr=ret->getPointer();
7499   std::fill(retPtr,retPtr+nbOfCells,-1);
7500   int newCellId=0;
7501   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7502     {
7503       for(const int *i=connI;i!=connI+nbOfCells;i++)
7504         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7505           retPtr[std::distance(connI,i)]=newCellId++;
7506     }
7507   renumberCells(retPtr,false);
7508   return ret;
7509 }
7510
7511 /*!
7512  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7513  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7514  * This method makes asumption that connectivity is correctly set before calling.
7515  */
7516 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7517 {
7518   checkConnectivityFullyDefined();
7519   const int *conn=_nodal_connec->begin();
7520   const int *connI=_nodal_connec_index->begin();
7521   int nbOfCells=getNumberOfCells();
7522   std::vector<MEDCouplingUMesh *> ret;
7523   for(const int *i=connI;i!=connI+nbOfCells;)
7524     {
7525       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7526       int beginCellId=(int)std::distance(connI,i);
7527       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,(int)curType));
7528       int endCellId=(int)std::distance(connI,i);
7529       int sz=endCellId-beginCellId;
7530       int *cells=new int[sz];
7531       for(int j=0;j<sz;j++)
7532         cells[j]=beginCellId+j;
7533       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7534       delete [] cells;
7535       ret.push_back(m);
7536     }
7537   return ret;
7538 }
7539
7540 /*!
7541  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7542  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7543  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7544  *
7545  * \return a newly allocated instance, that the caller must manage.
7546  * \throw If \a this contains more than one geometric type.
7547  * \throw If the nodal connectivity of \a this is not fully defined.
7548  * \throw If the internal data is not coherent.
7549  */
7550 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7551 {
7552   checkConnectivityFullyDefined();
7553   if(_types.size()!=1)
7554     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7555   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7556   MCAuto<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7557   ret->setCoords(getCoords());
7558   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7559   if(retC)
7560     {
7561       MCAuto<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7562       retC->setNodalConnectivity(c);
7563     }
7564   else
7565     {
7566       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7567       if(!retD)
7568         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7569       DataArrayInt *c=0,*ci=0;
7570       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7571       MCAuto<DataArrayInt> cs(c),cis(ci);
7572       retD->setNodalConnectivity(cs,cis);
7573     }
7574   return ret.retn();
7575 }
7576
7577 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7578 {
7579   checkConnectivityFullyDefined();
7580   if(_types.size()!=1)
7581     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7582   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7583   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7584   if(cm.isDynamic())
7585     {
7586       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7587       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7588       throw INTERP_KERNEL::Exception(oss.str());
7589     }
7590   int nbCells=getNumberOfCells();
7591   int typi=(int)typ;
7592   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7593   MCAuto<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7594   int *outPtr=connOut->getPointer();
7595   const int *conn=_nodal_connec->begin();
7596   const int *connI=_nodal_connec_index->begin();
7597   nbNodesPerCell++;
7598   for(int i=0;i<nbCells;i++,connI++)
7599     {
7600       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7601         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7602       else
7603         {
7604           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 << ") !";
7605           throw INTERP_KERNEL::Exception(oss.str());
7606         }
7607     }
7608   return connOut.retn();
7609 }
7610
7611 /*!
7612  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7613  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7614  * \param nodalConn
7615  * \param nodalConnI
7616  */
7617 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7618 {
7619   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkConsistency !";
7620   checkConnectivityFullyDefined();
7621   if(_types.size()!=1)
7622     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7623   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7624   if(lgth<nbCells)
7625     throw INTERP_KERNEL::Exception(msg0);
7626   MCAuto<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7627   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7628   int *cp(c->getPointer()),*cip(ci->getPointer());
7629   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7630   cip[0]=0;
7631   for(int i=0;i<nbCells;i++,cip++,incip++)
7632     {
7633       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7634       int delta(stop-strt);
7635       if(delta>=1)
7636         {
7637           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7638             cp=std::copy(incp+strt,incp+stop,cp);
7639           else
7640             throw INTERP_KERNEL::Exception(msg0);
7641         }
7642       else
7643         throw INTERP_KERNEL::Exception(msg0);
7644       cip[1]=cip[0]+delta;
7645     }
7646   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7647 }
7648
7649 /*!
7650  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7651  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7652  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7653  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7654  * are not used here to avoid the build of big permutation array.
7655  *
7656  * \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
7657  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7658  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7659  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7660  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7661  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7662  * \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
7663  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7664  */
7665 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7666                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7667                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7668 {
7669   std::vector<const MEDCouplingUMesh *> ms2;
7670   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7671     if(*it)
7672       {
7673         (*it)->checkConnectivityFullyDefined();
7674         ms2.push_back(*it);
7675       }
7676   if(ms2.empty())
7677     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7678   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7679   int meshDim=ms2[0]->getMeshDimension();
7680   std::vector<const MEDCouplingUMesh *> m1ssm;
7681   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmAuto;
7682   //
7683   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7684   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmSingleAuto;
7685   int fake=0,rk=0;
7686   MCAuto<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7687   ret1->alloc(0,1); ret2->alloc(0,1);
7688   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7689     {
7690       if(meshDim!=(*it)->getMeshDimension())
7691         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7692       if(refCoo!=(*it)->getCoords())
7693         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7694       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7695       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7696       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MCAuto<MEDCouplingUMesh> > >(m1ssmAuto));
7697       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7698         {
7699           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7700           m1ssmSingleAuto.push_back(singleCell);
7701           m1ssmSingle.push_back(singleCell);
7702           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7703         }
7704     }
7705   MCAuto<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7706   MCAuto<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7707   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7708   for(std::size_t i=0;i<m1ssm.size();i++)
7709     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7710   MCAuto<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7711   szOfCellGrpOfSameType=ret1->renumber(renum->begin());
7712   idInMsOfCellGrpOfSameType=ret2->renumber(renum->begin());
7713   return ret0.retn();
7714 }
7715
7716 /*!
7717  * This method returns a newly created DataArrayInt instance.
7718  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7719  */
7720 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7721 {
7722   checkFullyDefined();
7723   const int *conn=_nodal_connec->begin();
7724   const int *connIndex=_nodal_connec_index->begin();
7725   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7726   for(const int *w=begin;w!=end;w++)
7727     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7728       ret->pushBackSilent(*w);
7729   return ret.retn();
7730 }
7731
7732 /*!
7733  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7734  * are in [0:getNumberOfCells())
7735  */
7736 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7737 {
7738   checkFullyDefined();
7739   const int *conn=_nodal_connec->begin();
7740   const int *connI=_nodal_connec_index->begin();
7741   int nbOfCells=getNumberOfCells();
7742   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7743   int *tmp=new int[nbOfCells];
7744   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7745     {
7746       int j=0;
7747       for(const int *i=connI;i!=connI+nbOfCells;i++)
7748         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7749           tmp[std::distance(connI,i)]=j++;
7750     }
7751   DataArrayInt *ret=DataArrayInt::New();
7752   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7753   ret->copyStringInfoFrom(*da);
7754   int *retPtr=ret->getPointer();
7755   const int *daPtr=da->begin();
7756   int nbOfElems=da->getNbOfElems();
7757   for(int k=0;k<nbOfElems;k++)
7758     retPtr[k]=tmp[daPtr[k]];
7759   delete [] tmp;
7760   return ret;
7761 }
7762
7763 /*!
7764  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7765  * This method \b works \b for mesh sorted by type.
7766  * cells whose ids is in 'idsPerGeoType' array.
7767  * This method conserves coords and name of mesh.
7768  */
7769 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7770 {
7771   std::vector<int> code=getDistributionOfTypes();
7772   std::size_t nOfTypesInThis=code.size()/3;
7773   int sz=0,szOfType=0;
7774   for(std::size_t i=0;i<nOfTypesInThis;i++)
7775     {
7776       if(code[3*i]!=type)
7777         sz+=code[3*i+1];
7778       else
7779         szOfType=code[3*i+1];
7780     }
7781   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7782     if(*work<0 || *work>=szOfType)
7783       {
7784         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7785         oss << ". It should be in [0," << szOfType << ") !";
7786         throw INTERP_KERNEL::Exception(oss.str());
7787       }
7788   MCAuto<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7789   int *idsPtr=idsTokeep->getPointer();
7790   int offset=0;
7791   for(std::size_t i=0;i<nOfTypesInThis;i++)
7792     {
7793       if(code[3*i]!=type)
7794         for(int j=0;j<code[3*i+1];j++)
7795           *idsPtr++=offset+j;
7796       else
7797         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7798       offset+=code[3*i+1];
7799     }
7800   MCAuto<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7801   ret->copyTinyInfoFrom(this);
7802   return ret.retn();
7803 }
7804
7805 /*!
7806  * This method returns a vector of size 'this->getNumberOfCells()'.
7807  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7808  */
7809 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7810 {
7811   int ncell=getNumberOfCells();
7812   std::vector<bool> ret(ncell);
7813   const int *cI=getNodalConnectivityIndex()->begin();
7814   const int *c=getNodalConnectivity()->begin();
7815   for(int i=0;i<ncell;i++)
7816     {
7817       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7818       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7819       ret[i]=cm.isQuadratic();
7820     }
7821   return ret;
7822 }
7823
7824 /*!
7825  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7826  */
7827 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7828 {
7829   if(other->getType()!=UNSTRUCTURED)
7830     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7831   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7832   return MergeUMeshes(this,otherC);
7833 }
7834
7835 /*!
7836  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7837  * computed by averaging coordinates of cell nodes, so this method is not a right
7838  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7839  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7840  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7841  *          components. The caller is to delete this array using decrRef() as it is
7842  *          no more needed.
7843  *  \throw If the coordinates array is not set.
7844  *  \throw If the nodal connectivity of cells is not defined.
7845  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7846  */
7847 DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMass() const
7848 {
7849   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
7850   int spaceDim=getSpaceDimension();
7851   int nbOfCells=getNumberOfCells();
7852   ret->alloc(nbOfCells,spaceDim);
7853   ret->copyStringInfoFrom(*getCoords());
7854   double *ptToFill=ret->getPointer();
7855   const int *nodal=_nodal_connec->begin();
7856   const int *nodalI=_nodal_connec_index->begin();
7857   const double *coor=_coords->begin();
7858   for(int i=0;i<nbOfCells;i++)
7859     {
7860       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7861       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7862       ptToFill+=spaceDim;
7863     }
7864   return ret.retn();
7865 }
7866
7867 /*!
7868  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7869  * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the 
7870  * 
7871  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7872  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7873  * 
7874  * \sa MEDCouplingUMesh::computeCellCenterOfMass
7875  * \throw If \a this is not fully defined (coordinates and connectivity)
7876  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7877  */
7878 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7879 {
7880   checkFullyDefined();
7881   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
7882   int spaceDim=getSpaceDimension();
7883   int nbOfCells=getNumberOfCells();
7884   int nbOfNodes=getNumberOfNodes();
7885   ret->alloc(nbOfCells,spaceDim);
7886   double *ptToFill=ret->getPointer();
7887   const int *nodal=_nodal_connec->begin();
7888   const int *nodalI=_nodal_connec_index->begin();
7889   const double *coor=_coords->begin();
7890   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7891     {
7892       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7893       std::fill(ptToFill,ptToFill+spaceDim,0.);
7894       if(type!=INTERP_KERNEL::NORM_POLYHED)
7895         {
7896           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7897             {
7898               if(*conn>=0 && *conn<nbOfNodes)
7899                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7900               else
7901                 {
7902                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7903                   throw INTERP_KERNEL::Exception(oss.str());
7904                 }
7905             }
7906           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7907           if(nbOfNodesInCell>0)
7908             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7909           else
7910             {
7911               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7912               throw INTERP_KERNEL::Exception(oss.str());
7913             }
7914         }
7915       else
7916         {
7917           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7918           s.erase(-1);
7919           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7920             {
7921               if(*it>=0 && *it<nbOfNodes)
7922                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7923               else
7924                 {
7925                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7926                   throw INTERP_KERNEL::Exception(oss.str());
7927                 }
7928             }
7929           if(!s.empty())
7930             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7931           else
7932             {
7933               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7934               throw INTERP_KERNEL::Exception(oss.str());
7935             }
7936         }
7937     }
7938   return ret.retn();
7939 }
7940
7941 /*!
7942  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7943  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7944  * are specified via an array of cell ids. 
7945  *  \warning Validity of the specified cell ids is not checked! 
7946  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7947  *  \param [in] begin - an array of cell ids of interest.
7948  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7949  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7950  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7951  *          caller is to delete this array using decrRef() as it is no more needed. 
7952  *  \throw If the coordinates array is not set.
7953  *  \throw If the nodal connectivity of cells is not defined.
7954  *
7955  *  \if ENABLE_EXAMPLES
7956  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7957  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7958  *  \endif
7959  */
7960 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7961 {
7962   DataArrayDouble *ret=DataArrayDouble::New();
7963   int spaceDim=getSpaceDimension();
7964   int nbOfTuple=(int)std::distance(begin,end);
7965   ret->alloc(nbOfTuple,spaceDim);
7966   double *ptToFill=ret->getPointer();
7967   double *tmp=new double[spaceDim];
7968   const int *nodal=_nodal_connec->begin();
7969   const int *nodalI=_nodal_connec_index->begin();
7970   const double *coor=_coords->begin();
7971   for(const int *w=begin;w!=end;w++)
7972     {
7973       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7974       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7975       ptToFill+=spaceDim;
7976     }
7977   delete [] tmp;
7978   return ret;
7979 }
7980
7981 /*!
7982  * 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".
7983  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7984  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7985  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7986  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7987  * 
7988  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7989  * \throw If spaceDim!=3 or meshDim!=2.
7990  * \throw If connectivity of \a this is invalid.
7991  * \throw If connectivity of a cell in \a this points to an invalid node.
7992  */
7993 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7994 {
7995   MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
7996   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7997   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7998     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7999   ret->alloc(nbOfCells,4);
8000   double *retPtr(ret->getPointer());
8001   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
8002   const double *coor(_coords->begin());
8003   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
8004     {
8005       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
8006       if(nodalI[1]-nodalI[0]>=3)
8007         {
8008           for(int j=0;j<3;j++)
8009             {
8010               int nodeId(nodal[nodalI[0]+1+j]);
8011               if(nodeId>=0 && nodeId<nbOfNodes)
8012                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
8013               else
8014                 {
8015                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
8016                   throw INTERP_KERNEL::Exception(oss.str());
8017                 }
8018             }
8019         }
8020       else
8021         {
8022           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
8023           throw INTERP_KERNEL::Exception(oss.str());
8024         }
8025       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
8026       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
8027     }
8028   return ret.retn();
8029 }
8030
8031 /*!
8032  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
8033  * 
8034  */
8035 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
8036 {
8037   if(!da)
8038     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
8039   da->checkAllocated();
8040   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
8041   ret->setCoords(da);
8042   int nbOfTuples=da->getNumberOfTuples();
8043   MCAuto<DataArrayInt> c=DataArrayInt::New();
8044   MCAuto<DataArrayInt> cI=DataArrayInt::New();
8045   c->alloc(2*nbOfTuples,1);
8046   cI->alloc(nbOfTuples+1,1);
8047   int *cp=c->getPointer();
8048   int *cip=cI->getPointer();
8049   *cip++=0;
8050   for(int i=0;i<nbOfTuples;i++)
8051     {
8052       *cp++=INTERP_KERNEL::NORM_POINT1;
8053       *cp++=i;
8054       *cip++=2*(i+1);
8055     }
8056   ret->setConnectivity(c,cI,true);
8057   return ret.retn();
8058 }
8059 /*!
8060  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
8061  * Cells and nodes of
8062  * the first mesh precede cells and nodes of the second mesh within the result mesh.
8063  *  \param [in] mesh1 - the first mesh.
8064  *  \param [in] mesh2 - the second mesh.
8065  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8066  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8067  *          is no more needed.
8068  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
8069  *  \throw If the coordinates array is not set in none of the meshes.
8070  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
8071  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
8072  */
8073 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
8074 {
8075   std::vector<const MEDCouplingUMesh *> tmp(2);
8076   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
8077   return MergeUMeshes(tmp);
8078 }
8079
8080 /*!
8081  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
8082  * Cells and nodes of
8083  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
8084  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
8085  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8086  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8087  *          is no more needed.
8088  *  \throw If \a a.size() == 0.
8089  *  \throw If \a a[ *i* ] == NULL.
8090  *  \throw If the coordinates array is not set in none of the meshes.
8091  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
8092  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
8093  */
8094 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const std::vector<const MEDCouplingUMesh *>& a)
8095 {
8096   std::size_t sz=a.size();
8097   if(sz==0)
8098     return MergeUMeshesLL(a);
8099   for(std::size_t ii=0;ii<sz;ii++)
8100     if(!a[ii])
8101       {
8102         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
8103         throw INTERP_KERNEL::Exception(oss.str());
8104       }
8105   std::vector< MCAuto<MEDCouplingUMesh> > bb(sz);
8106   std::vector< const MEDCouplingUMesh * > aa(sz);
8107   int spaceDim=-3;
8108   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
8109     {
8110       const MEDCouplingUMesh *cur=a[i];
8111       const DataArrayDouble *coo=cur->getCoords();
8112       if(coo)
8113         spaceDim=coo->getNumberOfComponents();
8114     }
8115   if(spaceDim==-3)
8116     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
8117   for(std::size_t i=0;i<sz;i++)
8118     {
8119       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
8120       aa[i]=bb[i];
8121     }
8122   return MergeUMeshesLL(aa);
8123 }
8124
8125 /// @cond INTERNAL
8126
8127 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(const std::vector<const MEDCouplingUMesh *>& a)
8128 {
8129   if(a.empty())
8130     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
8131   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
8132   int meshDim=(*it)->getMeshDimension();
8133   int nbOfCells=(*it)->getNumberOfCells();
8134   int meshLgth=(*it++)->getNodalConnectivityArrayLen();
8135   for(;it!=a.end();it++)
8136     {
8137       if(meshDim!=(*it)->getMeshDimension())
8138         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
8139       nbOfCells+=(*it)->getNumberOfCells();
8140       meshLgth+=(*it)->getNodalConnectivityArrayLen();
8141     }
8142   std::vector<const MEDCouplingPointSet *> aps(a.size());
8143   std::copy(a.begin(),a.end(),aps.begin());
8144   MCAuto<DataArrayDouble> pts=MergeNodesArray(aps);
8145   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
8146   ret->setCoords(pts);
8147   MCAuto<DataArrayInt> c=DataArrayInt::New();
8148   c->alloc(meshLgth,1);
8149   int *cPtr=c->getPointer();
8150   MCAuto<DataArrayInt> cI=DataArrayInt::New();
8151   cI->alloc(nbOfCells+1,1);
8152   int *cIPtr=cI->getPointer();
8153   *cIPtr++=0;
8154   int offset=0;
8155   int offset2=0;
8156   for(it=a.begin();it!=a.end();it++)
8157     {
8158       int curNbOfCell=(*it)->getNumberOfCells();
8159       const int *curCI=(*it)->_nodal_connec_index->begin();
8160       const int *curC=(*it)->_nodal_connec->begin();
8161       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
8162       for(int j=0;j<curNbOfCell;j++)
8163         {
8164           const int *src=curC+curCI[j];
8165           *cPtr++=*src++;
8166           for(;src!=curC+curCI[j+1];src++,cPtr++)
8167             {
8168               if(*src!=-1)
8169                 *cPtr=*src+offset2;
8170               else
8171                 *cPtr=-1;
8172             }
8173         }
8174       offset+=curCI[curNbOfCell];
8175       offset2+=(*it)->getNumberOfNodes();
8176     }
8177   //
8178   ret->setConnectivity(c,cI,true);
8179   return ret.retn();
8180 }
8181
8182 /// @endcond
8183
8184 /*!
8185  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
8186  * dimension and sharing the node coordinates array.
8187  * All cells of the first mesh precede all cells of the second mesh
8188  * within the result mesh. 
8189  *  \param [in] mesh1 - the first mesh.
8190  *  \param [in] mesh2 - the second mesh.
8191  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8192  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8193  *          is no more needed.
8194  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
8195  *  \throw If the meshes do not share the node coordinates array.
8196  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
8197  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
8198  */
8199 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
8200 {
8201   std::vector<const MEDCouplingUMesh *> tmp(2);
8202   tmp[0]=mesh1; tmp[1]=mesh2;
8203   return MergeUMeshesOnSameCoords(tmp);
8204 }
8205
8206 /*!
8207  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8208  * dimension and sharing the node coordinates array.
8209  * All cells of the *i*-th mesh precede all cells of the
8210  * (*i*+1)-th mesh within the result mesh.
8211  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8212  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8213  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8214  *          is no more needed.
8215  *  \throw If \a a.size() == 0.
8216  *  \throw If \a a[ *i* ] == NULL.
8217  *  \throw If the meshes do not share the node coordinates array.
8218  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
8219  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
8220  */
8221 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
8222 {
8223   if(meshes.empty())
8224     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
8225   for(std::size_t ii=0;ii<meshes.size();ii++)
8226     if(!meshes[ii])
8227       {
8228         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
8229         throw INTERP_KERNEL::Exception(oss.str());
8230       }
8231   const DataArrayDouble *coords=meshes.front()->getCoords();
8232   int meshDim=meshes.front()->getMeshDimension();
8233   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
8234   int meshLgth=0;
8235   int meshIndexLgth=0;
8236   for(;iter!=meshes.end();iter++)
8237     {
8238       if(coords!=(*iter)->getCoords())
8239         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
8240       if(meshDim!=(*iter)->getMeshDimension())
8241         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8242       meshLgth+=(*iter)->getNodalConnectivityArrayLen();
8243       meshIndexLgth+=(*iter)->getNumberOfCells();
8244     }
8245   MCAuto<DataArrayInt> nodal=DataArrayInt::New();
8246   nodal->alloc(meshLgth,1);
8247   int *nodalPtr=nodal->getPointer();
8248   MCAuto<DataArrayInt> nodalIndex=DataArrayInt::New();
8249   nodalIndex->alloc(meshIndexLgth+1,1);
8250   int *nodalIndexPtr=nodalIndex->getPointer();
8251   int offset=0;
8252   for(iter=meshes.begin();iter!=meshes.end();iter++)
8253     {
8254       const int *nod=(*iter)->getNodalConnectivity()->begin();
8255       const int *index=(*iter)->getNodalConnectivityIndex()->begin();
8256       int nbOfCells=(*iter)->getNumberOfCells();
8257       int meshLgth2=(*iter)->getNodalConnectivityArrayLen();
8258       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8259       if(iter!=meshes.begin())
8260         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8261       else
8262         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8263       offset+=meshLgth2;
8264     }
8265   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8266   ret->setName("merge");
8267   ret->setMeshDimension(meshDim);
8268   ret->setConnectivity(nodal,nodalIndex,true);
8269   ret->setCoords(coords);
8270   return ret;
8271 }
8272
8273 /*!
8274  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8275  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8276  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8277  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8278  * New" mode are returned for each input mesh.
8279  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8280  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
8281  *          valid values [0,1,2], see zipConnectivityTraducer().
8282  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8283  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8284  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
8285  *          no more needed.
8286  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8287  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8288  *          is no more needed.
8289  *  \throw If \a meshes.size() == 0.
8290  *  \throw If \a meshes[ *i* ] == NULL.
8291  *  \throw If the meshes do not share the node coordinates array.
8292  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8293  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
8294  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8295  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
8296  */
8297 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8298 {
8299   //All checks are delegated to MergeUMeshesOnSameCoords
8300   MCAuto<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8301   MCAuto<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8302   corr.resize(meshes.size());
8303   std::size_t nbOfMeshes=meshes.size();
8304   int offset=0;
8305   const int *o2nPtr=o2n->begin();
8306   for(std::size_t i=0;i<nbOfMeshes;i++)
8307     {
8308       DataArrayInt *tmp=DataArrayInt::New();
8309       int curNbOfCells=meshes[i]->getNumberOfCells();
8310       tmp->alloc(curNbOfCells,1);
8311       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8312       offset+=curNbOfCells;
8313       tmp->setName(meshes[i]->getName());
8314       corr[i]=tmp;
8315     }
8316   return ret.retn();
8317 }
8318
8319 /*!
8320  * Makes all given meshes share the nodal connectivity array. The common connectivity
8321  * array is created by concatenating the connectivity arrays of all given meshes. All
8322  * the given meshes must be of the same space dimension but dimension of cells **can
8323  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8324  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8325  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8326  *  \param [in,out] meshes - a vector of meshes to update.
8327  *  \throw If any of \a meshes is NULL.
8328  *  \throw If the coordinates array is not set in any of \a meshes.
8329  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8330  *  \throw If \a meshes are of different space dimension.
8331  */
8332 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8333 {
8334   std::size_t sz=meshes.size();
8335   if(sz==0 || sz==1)
8336     return;
8337   std::vector< const DataArrayDouble * > coords(meshes.size());
8338   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8339   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8340     {
8341       if((*it))
8342         {
8343           (*it)->checkConnectivityFullyDefined();
8344           const DataArrayDouble *coo=(*it)->getCoords();
8345           if(coo)
8346             *it2=coo;
8347           else
8348             {
8349               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8350               oss << " has no coordinate array defined !";
8351               throw INTERP_KERNEL::Exception(oss.str());
8352             }
8353         }
8354       else
8355         {
8356           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8357           oss << " is null !";
8358           throw INTERP_KERNEL::Exception(oss.str());
8359         }
8360     }
8361   MCAuto<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8362   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8363   int offset=(*it)->getNumberOfNodes();
8364   (*it++)->setCoords(res);
8365   for(;it!=meshes.end();it++)
8366     {
8367       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8368       (*it)->setCoords(res);
8369       (*it)->shiftNodeNumbersInConn(offset);
8370       offset+=oldNumberOfNodes;
8371     }
8372 }
8373
8374 /*!
8375  * Merges nodes coincident with a given precision within all given meshes that share
8376  * the nodal connectivity array. The given meshes **can be of different** mesh
8377  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8378  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8379  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8380  *  \param [in,out] meshes - a vector of meshes to update.
8381  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8382  *  \throw If any of \a meshes is NULL.
8383  *  \throw If the \a meshes do not share the same node coordinates array.
8384  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8385  */
8386 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8387 {
8388   if(meshes.empty())
8389     return ;
8390   std::set<const DataArrayDouble *> s;
8391   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8392     {
8393       if(*it)
8394         s.insert((*it)->getCoords());
8395       else
8396         {
8397           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 !";
8398           throw INTERP_KERNEL::Exception(oss.str());
8399         }
8400     }
8401   if(s.size()!=1)
8402     {
8403       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 !";
8404       throw INTERP_KERNEL::Exception(oss.str());
8405     }
8406   const DataArrayDouble *coo=*(s.begin());
8407   if(!coo)
8408     return;
8409   //
8410   DataArrayInt *comm,*commI;
8411   coo->findCommonTuples(eps,-1,comm,commI);
8412   MCAuto<DataArrayInt> tmp1(comm),tmp2(commI);
8413   int oldNbOfNodes=coo->getNumberOfTuples();
8414   int newNbOfNodes;
8415   MCAuto<DataArrayInt> o2n=DataArrayInt::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8416   if(oldNbOfNodes==newNbOfNodes)
8417     return ;
8418   MCAuto<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->begin(),newNbOfNodes);
8419   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8420     {
8421       (*it)->renumberNodesInConn(o2n->begin());
8422       (*it)->setCoords(newCoords);
8423     } 
8424 }
8425
8426 /*!
8427  * 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.
8428  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8429  * \param isQuad specifies the policy of connectivity.
8430  * @ret in/out parameter in which the result will be append
8431  */
8432 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8433 {
8434   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8435   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8436   ret.push_back(cm.getExtrudedType());
8437   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8438   switch(flatType)
8439   {
8440     case INTERP_KERNEL::NORM_POINT1:
8441       {
8442         ret.push_back(connBg[1]);
8443         ret.push_back(connBg[1]+nbOfNodesPerLev);
8444         break;
8445       }
8446     case INTERP_KERNEL::NORM_SEG2:
8447       {
8448         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8449         ret.insert(ret.end(),conn,conn+4);
8450         break;
8451       }
8452     case INTERP_KERNEL::NORM_SEG3:
8453       {
8454         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8455         ret.insert(ret.end(),conn,conn+8);
8456         break;
8457       }
8458     case INTERP_KERNEL::NORM_QUAD4:
8459       {
8460         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8461         ret.insert(ret.end(),conn,conn+8);
8462         break;
8463       }
8464     case INTERP_KERNEL::NORM_TRI3:
8465       {
8466         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8467         ret.insert(ret.end(),conn,conn+6);
8468         break;
8469       }
8470     case INTERP_KERNEL::NORM_TRI6:
8471       {
8472         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,
8473           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8474         ret.insert(ret.end(),conn,conn+15);
8475         break;
8476       }
8477     case INTERP_KERNEL::NORM_QUAD8:
8478       {
8479         int conn[20]={
8480           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8481           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8482           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8483         };
8484         ret.insert(ret.end(),conn,conn+20);
8485         break;
8486       }
8487     case INTERP_KERNEL::NORM_POLYGON:
8488       {
8489         std::back_insert_iterator< std::vector<int> > ii(ret);
8490         std::copy(connBg+1,connEnd,ii);
8491         *ii++=-1;
8492         std::reverse_iterator<const int *> rConnBg(connEnd);
8493         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8494         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8495         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8496         for(std::size_t i=0;i<nbOfRadFaces;i++)
8497           {
8498             *ii++=-1;
8499             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8500             std::copy(conn,conn+4,ii);
8501           }
8502         break;
8503       }
8504     default:
8505       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8506   }
8507 }
8508
8509 /*!
8510  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8511  */
8512 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8513 {
8514   std::size_t i, ip1;
8515   double v[3]={0.,0.,0.};
8516   std::size_t sz=std::distance(begin,end);
8517   if(isQuadratic)
8518     sz/=2;
8519   for(i=0;i<sz;i++)
8520     {
8521       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];
8522       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8523       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8524     }
8525   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8526
8527   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8528   // SEG3 forming a circle):
8529   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8530     {
8531       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8532       for(std::size_t j=0;j<sz;j++)
8533         {
8534           if (j%2)  // current point i is quadratic, next point i+1 is standard
8535             {
8536               i = sz+j;
8537               ip1 = (j+1)%sz; // ip1 = "i+1"
8538             }
8539           else      // current point i is standard, next point i+1 is quadratic
8540             {
8541               i = j;
8542               ip1 = j+sz;
8543             }
8544           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8545           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8546           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8547         }
8548       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8549     }
8550   return (ret>0.);
8551 }
8552
8553 /*!
8554  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8555  */
8556 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8557 {
8558   std::vector<std::pair<int,int> > edges;
8559   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8560   const int *bgFace=begin;
8561   for(std::size_t i=0;i<nbOfFaces;i++)
8562     {
8563       const int *endFace=std::find(bgFace+1,end,-1);
8564       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8565       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8566         {
8567           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8568           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8569             return false;
8570           edges.push_back(p1);
8571         }
8572       bgFace=endFace+1;
8573     }
8574   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8575 }
8576
8577 /*!
8578  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8579  */
8580 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8581 {
8582   double vec0[3],vec1[3];
8583   std::size_t sz=std::distance(begin,end);
8584   if(sz%2!=0)
8585     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8586   int nbOfNodes=(int)sz/2;
8587   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8588   const double *pt0=coords+3*begin[0];
8589   const double *pt1=coords+3*begin[nbOfNodes];
8590   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8591   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8592 }
8593
8594 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8595 {
8596   std::size_t sz=std::distance(begin,end);
8597   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8598   std::size_t nbOfNodes(sz/2);
8599   std::copy(begin,end,(int *)tmp);
8600   for(std::size_t j=1;j<nbOfNodes;j++)
8601     {
8602       begin[j]=tmp[nbOfNodes-j];
8603       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8604     }
8605 }
8606
8607 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8608 {
8609   std::size_t sz=std::distance(begin,end);
8610   if(sz!=4)
8611     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkConsistency !");
8612   double vec0[3],vec1[3];
8613   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8614   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]; 
8615   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;
8616 }
8617
8618 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8619 {
8620   std::size_t sz=std::distance(begin,end);
8621   if(sz!=5)
8622     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkConsistency !");
8623   double vec0[3];
8624   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8625   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8626   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8627 }
8628
8629 /*!
8630  * 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 ) 
8631  * 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
8632  * a 2D space.
8633  *
8634  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8635  * \param [in] coords the coordinates with nb of components exactly equal to 3
8636  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8637  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8638  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8639  */
8640 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8641 {
8642   int nbFaces=std::count(begin+1,end,-1)+1;
8643   MCAuto<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8644   double *vPtr=v->getPointer();
8645   MCAuto<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8646   double *pPtr=p->getPointer();
8647   const int *stFaceConn=begin+1;
8648   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8649     {
8650       const int *endFaceConn=std::find(stFaceConn,end,-1);
8651       ComputeVecAndPtOfFace(eps,coords->begin(),stFaceConn,endFaceConn,vPtr,pPtr);
8652       stFaceConn=endFaceConn+1;
8653     }
8654   pPtr=p->getPointer(); vPtr=v->getPointer();
8655   DataArrayInt *comm1=0,*commI1=0;
8656   v->findCommonTuples(eps,-1,comm1,commI1);
8657   MCAuto<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8658   const int *comm1Ptr=comm1->begin();
8659   const int *commI1Ptr=commI1->begin();
8660   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8661   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8662   //
8663   MCAuto<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8664   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8665   mm->finishInsertingCells();
8666   //
8667   for(int i=0;i<nbOfGrps1;i++)
8668     {
8669       int vecId=comm1Ptr[commI1Ptr[i]];
8670       MCAuto<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8671       DataArrayInt *comm2=0,*commI2=0;
8672       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8673       MCAuto<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8674       const int *comm2Ptr=comm2->begin();
8675       const int *commI2Ptr=commI2->begin();
8676       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8677       for(int j=0;j<nbOfGrps2;j++)
8678         {
8679           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8680             {
8681               res->insertAtTheEnd(begin,end);
8682               res->pushBackSilent(-1);
8683             }
8684           else
8685             {
8686               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8687               MCAuto<DataArrayInt> ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1);
8688               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8689               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8690               MCAuto<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8691               MCAuto<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8692               MCAuto<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8693               MCAuto<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8694               const int *idsNodePtr=idsNode->begin();
8695               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];
8696               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8697               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8698               if(std::abs(norm)>eps)
8699                 {
8700                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8701                   mm3->rotate(center,vec,angle);
8702                 }
8703               mm3->changeSpaceDimension(2);
8704               MCAuto<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8705               const int *conn4=mm4->getNodalConnectivity()->begin();
8706               const int *connI4=mm4->getNodalConnectivityIndex()->begin();
8707               int nbOfCells=mm4->getNumberOfCells();
8708               for(int k=0;k<nbOfCells;k++)
8709                 {
8710                   int l=0;
8711                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8712                     res->pushBackSilent(idsNodePtr[*work]);
8713                   res->pushBackSilent(-1);
8714                 }
8715             }
8716         }
8717     }
8718   res->popBackSilent();
8719 }
8720
8721 /*!
8722  * 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
8723  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8724  * 
8725  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8726  * \param [in] coords coordinates expected to have 3 components.
8727  * \param [in] begin start of the nodal connectivity of the face.
8728  * \param [in] end end of the nodal connectivity (excluded) of the face.
8729  * \param [out] v the normalized vector of size 3
8730  * \param [out] p the pos of plane
8731  */
8732 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8733 {
8734   std::size_t nbPoints=std::distance(begin,end);
8735   if(nbPoints<3)
8736     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8737   double vec[3]={0.,0.,0.};
8738   std::size_t j=0;
8739   bool refFound=false;
8740   for(;j<nbPoints-1 && !refFound;j++)
8741     {
8742       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8743       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8744       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8745       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8746       if(norm>eps)
8747         {
8748           refFound=true;
8749           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8750         }
8751     }
8752   for(std::size_t i=j;i<nbPoints-1;i++)
8753     {
8754       double curVec[3];
8755       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8756       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8757       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8758       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8759       if(norm<eps)
8760         continue;
8761       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8762       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];
8763       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8764       if(norm>eps)
8765         {
8766           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8767           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8768           return ;
8769         }
8770     }
8771   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8772 }
8773
8774 /*!
8775  * This method tries to obtain a well oriented polyhedron.
8776  * If the algorithm fails, an exception will be thrown.
8777  */
8778 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8779 {
8780   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8781   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8782   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8783   isPerm[0]=true;
8784   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8785   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8786   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8787   //
8788   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8789     {
8790       bgFace=begin;
8791       std::size_t smthChanged=0;
8792       for(std::size_t i=0;i<nbOfFaces;i++)
8793         {
8794           endFace=std::find(bgFace+1,end,-1);
8795           nbOfEdgesInFace=std::distance(bgFace,endFace);
8796           if(!isPerm[i])
8797             {
8798               bool b;
8799               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8800                 {
8801                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8802                   std::pair<int,int> p2(p1.second,p1.first);
8803                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8804                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8805                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8806                 }
8807               if(isPerm[i])
8808                 { 
8809                   if(!b)
8810                     std::reverse(bgFace+1,endFace);
8811                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8812                     {
8813                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8814                       std::pair<int,int> p2(p1.second,p1.first);
8815                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8816                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
8817                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8818                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
8819                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8820                       if(it!=edgesOK.end())
8821                         {
8822                           edgesOK.erase(it);
8823                           edgesFinished.push_back(p1);
8824                         }
8825                       else
8826                         edgesOK.push_back(p1);
8827                     }
8828                 }
8829             }
8830           bgFace=endFace+1;
8831         }
8832       if(smthChanged==0)
8833         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8834     }
8835   if(!edgesOK.empty())
8836     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8837   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8838     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8839       bgFace=begin;
8840       for(std::size_t i=0;i<nbOfFaces;i++)
8841         {
8842           endFace=std::find(bgFace+1,end,-1);
8843           std::reverse(bgFace+1,endFace);
8844           bgFace=endFace+1;
8845         }
8846     }
8847 }
8848
8849 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8850 {
8851   int nbOfNodesExpected(skin->getNumberOfNodes());
8852   const int *n2oPtr(n2o->begin());
8853   MCAuto<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8854   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8855   const int *revNodalPtr(revNodal->begin()),*revNodalIPtr(revNodalI->begin());
8856   const int *nodalPtr(skin->getNodalConnectivity()->begin());
8857   const int *nodalIPtr(skin->getNodalConnectivityIndex()->begin());
8858   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8859   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8860   if(nbOfNodesExpected<1)
8861     return ret.retn();
8862   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8863   *work++=n2oPtr[prevNode];
8864   for(int i=1;i<nbOfNodesExpected;i++)
8865     {
8866       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8867         {
8868           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8869           conn.erase(prevNode);
8870           if(conn.size()==1)
8871             {
8872               int curNode(*(conn.begin()));
8873               *work++=n2oPtr[curNode];
8874               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8875               shar.erase(prevCell);
8876               if(shar.size()==1)
8877                 {
8878                   prevCell=*(shar.begin());
8879                   prevNode=curNode;
8880                 }
8881               else
8882                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8883             }
8884           else
8885             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8886         }
8887       else
8888         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8889     }
8890   return ret.retn();
8891 }
8892
8893 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8894 {
8895   int nbOfNodesExpected(skin->getNumberOfNodes());
8896   int nbOfTurn(nbOfNodesExpected/2);
8897   const int *n2oPtr(n2o->begin());
8898   MCAuto<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8899   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8900   const int *revNodalPtr(revNodal->begin()),*revNodalIPtr(revNodalI->begin());
8901   const int *nodalPtr(skin->getNodalConnectivity()->begin());
8902   const int *nodalIPtr(skin->getNodalConnectivityIndex()->begin());
8903   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8904   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8905   if(nbOfNodesExpected<1)
8906     return ret.retn();
8907   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8908   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8909   for(int i=1;i<nbOfTurn;i++)
8910     {
8911       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8912         {
8913           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8914           conn.erase(prevNode);
8915           if(conn.size()==1)
8916             {
8917               int curNode(*(conn.begin()));
8918               *work=n2oPtr[curNode];
8919               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8920               shar.erase(prevCell);
8921               if(shar.size()==1)
8922                 {
8923                   int curCell(*(shar.begin()));
8924                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8925                   prevCell=curCell;
8926                   prevNode=curNode;
8927                   work++;
8928                 }
8929               else
8930                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8931             }
8932           else
8933             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8934         }
8935       else
8936         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8937     }
8938   return ret.retn();
8939 }
8940
8941 /*!
8942  * This method makes the assumption spacedimension == meshdimension == 2.
8943  * This method works only for linear cells.
8944  * 
8945  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8946  */
8947 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8948 {
8949   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8950     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8951   MCAuto<MEDCouplingUMesh> skin(computeSkin());
8952   int oldNbOfNodes(skin->getNumberOfNodes());
8953   MCAuto<DataArrayInt> o2n(skin->zipCoordsTraducer());
8954   int nbOfNodesExpected(skin->getNumberOfNodes());
8955   MCAuto<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8956   int nbCells(skin->getNumberOfCells());
8957   if(nbCells==nbOfNodesExpected)
8958     return buildUnionOf2DMeshLinear(skin,n2o);
8959   else if(2*nbCells==nbOfNodesExpected)
8960     return buildUnionOf2DMeshQuadratic(skin,n2o);
8961   else
8962     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8963 }
8964
8965 /*!
8966  * This method makes the assumption spacedimension == meshdimension == 3.
8967  * This method works only for linear cells.
8968  * 
8969  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8970  */
8971 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8972 {
8973   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8974     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8975   MCAuto<MEDCouplingUMesh> m=computeSkin();
8976   const int *conn=m->getNodalConnectivity()->begin();
8977   const int *connI=m->getNodalConnectivityIndex()->begin();
8978   int nbOfCells=m->getNumberOfCells();
8979   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8980   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8981   if(nbOfCells<1)
8982     return ret.retn();
8983   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8984   for(int i=1;i<nbOfCells;i++)
8985     {
8986       *work++=-1;
8987       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8988     }
8989   return ret.retn();
8990 }
8991
8992 /*!
8993  * \brief Creates a graph of cell neighbors
8994  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8995  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
8996  *  For example
8997  *  - index:  0 3 5 6 6
8998  *  - value:  1 2 3 2 3 3
8999  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
9000  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
9001  */
9002 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
9003 {
9004   checkConnectivityFullyDefined();
9005
9006   int meshDim = this->getMeshDimension();
9007   MEDCoupling::DataArrayInt* indexr=MEDCoupling::DataArrayInt::New();
9008   MEDCoupling::DataArrayInt* revConn=MEDCoupling::DataArrayInt::New();
9009   this->getReverseNodalConnectivity(revConn,indexr);
9010   const int* indexr_ptr=indexr->begin();
9011   const int* revConn_ptr=revConn->begin();
9012
9013   const MEDCoupling::DataArrayInt* index;
9014   const MEDCoupling::DataArrayInt* conn;
9015   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
9016   index=this->getNodalConnectivityIndex();
9017   int nbCells=this->getNumberOfCells();
9018   const int* index_ptr=index->begin();
9019   const int* conn_ptr=conn->begin();
9020
9021   //creating graph arcs (cell to cell relations)
9022   //arcs are stored in terms of (index,value) notation
9023   // 0 3 5 6 6
9024   // 1 2 3 2 3 3
9025   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
9026   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
9027
9028   //warning here one node have less than or equal effective number of cell with it
9029   //but cell could have more than effective nodes
9030   //because other equals nodes in other domain (with other global inode)
9031   std::vector <int> cell2cell_index(nbCells+1,0);
9032   std::vector <int> cell2cell;
9033   cell2cell.reserve(3*nbCells);
9034
9035   for (int icell=0; icell<nbCells;icell++)
9036     {
9037       std::map<int,int > counter;
9038       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
9039         {
9040           int inode=conn_ptr[iconn];
9041           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
9042             {
9043               int icell2=revConn_ptr[iconnr];
9044               std::map<int,int>::iterator iter=counter.find(icell2);
9045               if (iter!=counter.end()) (iter->second)++;
9046               else counter.insert(std::make_pair(icell2,1));
9047             }
9048         }
9049       for (std::map<int,int>::const_iterator iter=counter.begin();
9050            iter!=counter.end(); iter++)
9051         if (iter->second >= meshDim)
9052           {
9053             cell2cell_index[icell+1]++;
9054             cell2cell.push_back(iter->first);
9055           }
9056     }
9057   indexr->decrRef();
9058   revConn->decrRef();
9059   cell2cell_index[0]=0;
9060   for (int icell=0; icell<nbCells;icell++)
9061     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
9062
9063   //filling up index and value to create skylinearray structure
9064   MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
9065   return array;
9066 }
9067
9068 /*!
9069  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
9070  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
9071  */
9072 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
9073 {
9074   double *w=zipFrmt;
9075   if(spaceDim==3)
9076     for(int i=0;i<nbOfNodesInCell;i++)
9077       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
9078   else if(spaceDim==2)
9079     {
9080       for(int i=0;i<nbOfNodesInCell;i++)
9081         {
9082           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
9083           *w++=0.;
9084         }
9085     }
9086   else
9087     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
9088 }
9089
9090 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
9091 {
9092   int nbOfCells=getNumberOfCells();
9093   if(nbOfCells<=0)
9094     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
9095   ofs << "  <" << getVTKDataSetType() << ">\n";
9096   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
9097   ofs << "      <PointData>\n" << pointData << std::endl;
9098   ofs << "      </PointData>\n";
9099   ofs << "      <CellData>\n" << cellData << std::endl;
9100   ofs << "      </CellData>\n";
9101   ofs << "      <Points>\n";
9102   if(getSpaceDimension()==3)
9103     _coords->writeVTK(ofs,8,"Points",byteData);
9104   else
9105     {
9106       MCAuto<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
9107       coo->writeVTK(ofs,8,"Points",byteData);
9108     }
9109   ofs << "      </Points>\n";
9110   ofs << "      <Cells>\n";
9111   const int *cPtr=_nodal_connec->begin();
9112   const int *cIPtr=_nodal_connec_index->begin();
9113   MCAuto<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
9114   MCAuto<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
9115   MCAuto<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
9116   MCAuto<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
9117   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
9118   int szFaceOffsets=0,szConn=0;
9119   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
9120     {
9121       *w2=cPtr[cIPtr[i]];
9122       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
9123         {
9124           *w1=-1;
9125           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
9126           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
9127         }
9128       else
9129         {
9130           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
9131           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
9132           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
9133           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
9134           w4=std::copy(c.begin(),c.end(),w4);
9135         }
9136     }
9137   types->transformWithIndArr(MEDCOUPLING2VTKTYPETRADUCER,MEDCOUPLING2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
9138   types->writeVTK(ofs,8,"UInt8","types",byteData);
9139   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
9140   if(szFaceOffsets!=0)
9141     {//presence of Polyhedra
9142       connectivity->reAlloc(szConn);
9143       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
9144       MCAuto<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
9145       w1=faces->getPointer();
9146       for(int i=0;i<nbOfCells;i++)
9147         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
9148           {
9149             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
9150             *w1++=nbFaces;
9151             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
9152             for(int j=0;j<nbFaces;j++)
9153               {
9154                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
9155                 *w1++=(int)std::distance(w6,w5);
9156                 w1=std::copy(w6,w5,w1);
9157                 w6=w5+1;
9158               }
9159           }
9160       faces->writeVTK(ofs,8,"Int32","faces",byteData);
9161     }
9162   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
9163   ofs << "      </Cells>\n";
9164   ofs << "    </Piece>\n";
9165   ofs << "  </" << getVTKDataSetType() << ">\n";
9166 }
9167
9168 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
9169 {
9170   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
9171   if(_mesh_dim==-2)
9172     { stream << " Not set !"; return ; }
9173   stream << " Mesh dimension : " << _mesh_dim << ".";
9174   if(_mesh_dim==-1)
9175     return ;
9176   if(!_coords)
9177     { stream << " No coordinates set !"; return ; }
9178   if(!_coords->isAllocated())
9179     { stream << " Coordinates set but not allocated !"; return ; }
9180   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
9181   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
9182   if(!_nodal_connec_index)
9183     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
9184   if(!_nodal_connec_index->isAllocated())
9185     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
9186   int lgth=_nodal_connec_index->getNumberOfTuples();
9187   int cpt=_nodal_connec_index->getNumberOfComponents();
9188   if(cpt!=1 || lgth<1)
9189     return ;
9190   stream << std::endl << "Number of cells : " << lgth-1 << ".";
9191 }
9192
9193 std::string MEDCouplingUMesh::getVTKDataSetType() const
9194 {
9195   return std::string("UnstructuredGrid");
9196 }
9197
9198 std::string MEDCouplingUMesh::getVTKFileExtension() const
9199 {
9200   return std::string("vtu");
9201 }
9202
9203 /*!
9204  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
9205  * returns a result mesh constituted by polygons.
9206  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
9207  * all nodes from m2.
9208  * The meshes should be in 2D space. In
9209  * addition, returns two arrays mapping cells of the result mesh to cells of the input
9210  * meshes.
9211  *  \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
9212  *                      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)
9213  *  \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
9214  *                      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)
9215  *  \param [in] eps - precision used to detect coincident mesh entities.
9216  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
9217  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
9218  *         this array using decrRef() as it is no more needed.
9219  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
9220  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
9221  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
9222  *         any cell of \a m2. The caller is to delete this array using decrRef() as
9223  *         it is no more needed.  
9224  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
9225  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
9226  *         is no more needed.  
9227  *  \throw If the coordinates array is not set in any of the meshes.
9228  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
9229  *  \throw If any of the meshes is not a 2D mesh in 2D space.
9230  *
9231  *  \sa conformize2D, mergeNodes
9232  */
9233 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9234                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
9235 {
9236   if(!m1 || !m2)
9237     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
9238   m1->checkFullyDefined();
9239   m2->checkFullyDefined();
9240   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9241     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
9242
9243   // Step 1: compute all edge intersections (new nodes)
9244   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9245   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9246   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9247   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9248   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9249                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9250                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9251   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9252   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9253   MCAuto<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9254
9255   // Step 2: re-order newly created nodes according to the ordering found in m2
9256   std::vector< std::vector<int> > intersectEdge2;
9257   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9258   subDiv2.clear(); dd5=0; dd6=0;
9259
9260   // Step 3:
9261   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9262   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9263   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->begin(),descIndx1->begin(),intersectEdge1,colinear2,m2,desc2->begin(),descIndx2->begin(),intersectEdge2,addCoo,
9264                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9265
9266   // Step 4: Prepare final result:
9267   MCAuto<DataArrayDouble> addCooDa(DataArrayDouble::New());
9268   addCooDa->alloc((int)(addCoo.size())/2,2);
9269   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9270   MCAuto<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9271   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9272   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9273   std::vector<const DataArrayDouble *> coordss(4);
9274   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9275   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9276   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9277   MCAuto<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9278   MCAuto<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9279   MCAuto<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9280   MCAuto<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9281   ret->setConnectivity(conn,connI,true);
9282   ret->setCoords(coo);
9283   cellNb1=c1.retn(); cellNb2=c2.retn();
9284   return ret.retn();
9285 }
9286
9287 /// @cond INTERNAL
9288
9289 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9290 {
9291   if(candidates.empty())
9292     return false;
9293   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9294     {
9295       const std::vector<int>& pool(intersectEdge1[*it]);
9296       int tmp[2]; tmp[0]=start; tmp[1]=stop;
9297       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9298         {
9299           retVal=*it+1;
9300           return true;
9301         }
9302       tmp[0]=stop; tmp[1]=start;
9303       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9304         {
9305           retVal=-*it-1;
9306           return true;
9307         }
9308     }
9309   return false;
9310 }
9311
9312 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,
9313                                      MCAuto<DataArrayInt>& idsInRetColinear, MCAuto<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9314 {
9315   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9316   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9317   int nCells(mesh1D->getNumberOfCells());
9318   if(nCells!=(int)intersectEdge2.size())
9319     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9320   const DataArrayDouble *coo2(mesh1D->getCoords());
9321   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9322   const double *coo2Ptr(coo2->begin());
9323   int offset1(coords1->getNumberOfTuples());
9324   int offset2(offset1+coo2->getNumberOfTuples());
9325   int offset3(offset2+addCoo.size()/2);
9326   std::vector<double> addCooQuad;
9327   MCAuto<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9328   int tmp[4],cicnt(0),kk(0);
9329   for(int i=0;i<nCells;i++)
9330     {
9331       std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
9332       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9333       const std::vector<int>& subEdges(intersectEdge2[i]);
9334       int nbSubEdge(subEdges.size()/2);
9335       for(int j=0;j<nbSubEdge;j++,kk++)
9336         {
9337           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));
9338           MCAuto<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9339           INTERP_KERNEL::Edge *e2Ptr(e2);
9340           std::map<int,int>::const_iterator itm;
9341           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9342             {
9343               tmp[0]=INTERP_KERNEL::NORM_SEG3;
9344               itm=mergedNodes.find(subEdges[2*j]);
9345               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9346               itm=mergedNodes.find(subEdges[2*j+1]);
9347               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9348               tmp[3]=offset3+(int)addCooQuad.size()/2;
9349               double tmp2[2];
9350               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9351               cicnt+=4;
9352               cOut->insertAtTheEnd(tmp,tmp+4);
9353               ciOut->pushBackSilent(cicnt);
9354             }
9355           else
9356             {
9357               tmp[0]=INTERP_KERNEL::NORM_SEG2;
9358               itm=mergedNodes.find(subEdges[2*j]);
9359               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9360               itm=mergedNodes.find(subEdges[2*j+1]);
9361               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9362               cicnt+=3;
9363               cOut->insertAtTheEnd(tmp,tmp+3);
9364               ciOut->pushBackSilent(cicnt);
9365             }
9366           int tmp00;
9367           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9368             {
9369               idsInRetColinear->pushBackSilent(kk);
9370               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9371             }
9372         }
9373       e->decrRef();
9374     }
9375   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9376   ret->setConnectivity(cOut,ciOut,true);
9377   MCAuto<DataArrayDouble> arr3(DataArrayDouble::New());
9378   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9379   MCAuto<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9380   std::vector<const DataArrayDouble *> coordss(4);
9381   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9382   MCAuto<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9383   ret->setCoords(arr);
9384   return ret.retn();
9385 }
9386
9387 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9388 {
9389   std::vector<int> allEdges;
9390   for(const int *it2(descBg);it2!=descEnd;it2++)
9391     {
9392       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9393       if(*it2>0)
9394         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9395       else
9396         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9397     }
9398   std::size_t nb(allEdges.size());
9399   if(nb%2!=0)
9400     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9401   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9402   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9403   ret->setCoords(coords);
9404   ret->allocateCells(1);
9405   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9406   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9407     connOut[kk]=allEdges[2*kk];
9408   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9409   return ret.retn();
9410 }
9411
9412 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9413 {
9414   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9415   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9416   std::size_t ii(0);
9417   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9418   if(sz!=std::distance(descBg,descEnd))
9419     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9420   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9421   std::vector<int> allEdges,centers;
9422   const double *coordsPtr(coords->begin());
9423   MCAuto<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9424   int offset(coords->getNumberOfTuples());
9425   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9426     {
9427       INTERP_KERNEL::NormalizedCellType typeOfSon;
9428       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9429       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9430       if(*it2>0)
9431         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9432       else
9433         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9434       if(edge1.size()==2)
9435         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9436       else
9437         {//the current edge has been subsplit -> create corresponding centers.
9438           std::size_t nbOfCentersToAppend(edge1.size()/2);
9439           std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9440           MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9441           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9442           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9443             {
9444               double tmpp[2];
9445               const double *aa(coordsPtr+2*(*it3++));
9446               const double *bb(coordsPtr+2*(*it3++));
9447               ee->getMiddleOfPoints(aa,bb,tmpp);
9448               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9449               centers.push_back(offset+k);
9450             }
9451         }
9452     }
9453   std::size_t nb(allEdges.size());
9454   if(nb%2!=0)
9455     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9456   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9457   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9458   if(addCoo->empty())
9459     ret->setCoords(coords);
9460   else
9461     {
9462       addCoo->rearrange(2);
9463       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9464       ret->setCoords(addCoo);
9465     }
9466   ret->allocateCells(1);
9467   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9468   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9469     connOut[kk]=allEdges[2*kk];
9470   connOut.insert(connOut.end(),centers.begin(),centers.end());
9471   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9472   return ret.retn();
9473 }
9474
9475 /*!
9476  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9477  * of those edges.
9478  *
9479  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9480  */
9481 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9482 {
9483   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9484   if(!cm.isQuadratic())
9485     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9486   else
9487     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9488 }
9489
9490 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edges)
9491 {
9492   bool isQuad(false);
9493   for(std::vector< MCAuto<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9494     {
9495       const INTERP_KERNEL::Edge *ee(*it);
9496       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9497         isQuad=true;
9498     }
9499   if(!isQuad)
9500     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9501   else
9502     {
9503       const double *coo(mesh2D->getCoords()->begin());
9504       std::size_t sz(conn.size());
9505       std::vector<double> addCoo;
9506       std::vector<int> conn2(conn);
9507       int offset(mesh2D->getNumberOfNodes());
9508       for(std::size_t i=0;i<sz;i++)
9509         {
9510           double tmp[2];
9511           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9512           addCoo.insert(addCoo.end(),tmp,tmp+2);
9513           conn2.push_back(offset+(int)i);
9514         }
9515       mesh2D->getCoords()->rearrange(1);
9516       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9517       mesh2D->getCoords()->rearrange(2);
9518       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9519     }
9520 }
9521
9522 /*!
9523  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9524  *
9525  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9526  * a set of edges defined in \a splitMesh1D.
9527  */
9528 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edge1BisPtr,
9529                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > >& out1)
9530 {
9531   std::size_t nb(edge1Bis.size()/2);
9532   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9533   int iEnd(splitMesh1D->getNumberOfCells());
9534   if(iEnd==0)
9535     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9536   std::size_t ii,jj;
9537   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9538   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9539   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9540   //
9541   if(jj==nb)
9542     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9543       out0.resize(1); out1.resize(1);
9544       std::vector<int>& connOut(out0[0]);
9545       connOut.resize(nbOfEdgesOf2DCellSplit);
9546       std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9547       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9548       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9549         {
9550           connOut[kk]=edge1Bis[2*kk];
9551           edgesPtr[kk]=edge1BisPtr[2*kk];
9552         }
9553     }
9554   else
9555     {
9556       // [i,iEnd[ contains the
9557       out0.resize(2); out1.resize(2);
9558       std::vector<int>& connOutLeft(out0[0]);
9559       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9560       std::vector< MCAuto<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9561       std::vector< MCAuto<INTERP_KERNEL::Edge> >& eright(out1[1]);
9562       for(std::size_t k=ii;k<jj+1;k++)
9563         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9564       std::vector< MCAuto<INTERP_KERNEL::Edge> > ees(iEnd);
9565       for(int ik=0;ik<iEnd;ik++)
9566         {
9567           std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9568           MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9569           ees[ik]=ee;
9570         }
9571       for(int ik=iEnd-1;ik>=0;ik--)
9572         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9573       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9574         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9575       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9576       for(int ik=0;ik<iEnd;ik++)
9577         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9578       eright.insert(eright.end(),ees.begin(),ees.end());
9579     }
9580 }
9581
9582 /// @endcond
9583
9584 /// @cond INTERNAL
9585
9586 struct CellInfo
9587 {
9588 public:
9589   CellInfo() { }
9590   CellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr);
9591 public:
9592   std::vector<int> _edges;
9593   std::vector< MCAuto<INTERP_KERNEL::Edge> > _edges_ptr;
9594 };
9595
9596 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr)
9597 {
9598   std::size_t nbe(edges.size());
9599   std::vector<int> edges2(2*nbe); std::vector< MCAuto<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9600   for(std::size_t i=0;i<nbe;i++)
9601     {
9602       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9603       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9604     }
9605   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9606   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9607   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9608 }
9609
9610 class EdgeInfo
9611 {
9612 public:
9613   EdgeInfo(int istart, int iend, const MCAuto<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9614   EdgeInfo(int istart, int iend, int pos, const MCAuto<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9615   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9616   void somethingHappendAt(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight);
9617   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9618 private:
9619   int _istart;
9620   int _iend;
9621   MCAuto<MEDCouplingUMesh> _mesh;
9622   MCAuto<INTERP_KERNEL::Edge> _edge;
9623   int _left;
9624   int _right;
9625 };
9626
9627 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight)
9628 {
9629   const MEDCouplingUMesh *mesh(_mesh);
9630   if(mesh)
9631     return ;
9632   if(_right<pos)
9633     return ;
9634   if(_left>pos)
9635     { _left++; _right++; return ; }
9636   if(_right==pos)
9637     {
9638       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9639       if((isLeft && isRight) || (!isLeft && !isRight))
9640         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9641       if(isLeft)
9642         return ;
9643       if(isRight)
9644         {
9645           _right++;
9646           return ;
9647         }
9648     }
9649   if(_left==pos)
9650     {
9651       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9652       if((isLeft && isRight) || (!isLeft && !isRight))
9653         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9654       if(isLeft)
9655         {
9656           _right++;
9657           return ;
9658         }
9659       if(isRight)
9660         {
9661           _left++;
9662           _right++;
9663           return ;
9664         }
9665     }
9666 }
9667
9668 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9669 {
9670   const MEDCouplingUMesh *mesh(_mesh);
9671   if(!mesh)
9672     {
9673       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9674     }
9675   else
9676     {// not fully splitting cell case
9677       if(mesh2D->getNumberOfCells()==1)
9678         {//little optimization. 1 cell no need to find in which cell mesh is !
9679           neighbors[0]=offset; neighbors[1]=offset;
9680           return;
9681         }
9682       else
9683         {
9684           MCAuto<DataArrayDouble> barys(mesh->computeCellCenterOfMass());
9685           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9686           if(cellId==-1)
9687             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9688           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9689         }
9690     }
9691 }
9692
9693 class VectorOfCellInfo
9694 {
9695 public:
9696   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr);
9697   std::size_t size() const { return _pool.size(); }
9698   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9699   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);
9700   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9701   const std::vector< MCAuto<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9702   MCAuto<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9703   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9704 private:
9705   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9706   void updateEdgeInfo(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight);
9707   const CellInfo& get(int pos) const;
9708   CellInfo& get(int pos);
9709 private:
9710   std::vector<CellInfo> _pool;
9711   MCAuto<MEDCouplingUMesh> _ze_mesh;
9712   std::vector<EdgeInfo> _edge_info;
9713 };
9714
9715 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9716 {
9717   _pool[0]._edges=edges;
9718   _pool[0]._edges_ptr=edgesPtr;
9719 }
9720
9721 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9722 {
9723   if(_pool.empty())
9724     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9725   if(_pool.size()==1)
9726     return 0;
9727   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9728   if(!zeMesh)
9729     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9730   MCAuto<DataArrayDouble> barys(mesh->computeCellCenterOfMass());
9731   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9732 }
9733
9734 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)
9735 {
9736   get(pos);//to check pos
9737   bool isFast(pos==0 && _pool.size()==1);
9738   std::size_t sz(edges.size());
9739   // dealing with edges
9740   if(sz==1)
9741     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9742   else
9743     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9744   //
9745   std::vector<CellInfo> pool(_pool.size()-1+sz);
9746   for(int i=0;i<pos;i++)
9747     pool[i]=_pool[i];
9748   for(std::size_t j=0;j<sz;j++)
9749     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9750   for(int i=pos+1;i<(int)_pool.size();i++)
9751     pool[i+sz-1]=_pool[i];
9752   _pool=pool;
9753   //
9754   if(sz==2)
9755     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9756   //
9757   if(isFast)
9758     {
9759       _ze_mesh=mesh;
9760       return ;
9761     }
9762   //
9763   std::vector< MCAuto<MEDCouplingUMesh> > ms;
9764   if(pos>0)
9765     {
9766       MCAuto<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelfSlice(0,pos,true)));
9767       ms.push_back(elt);
9768     }
9769   ms.push_back(mesh);
9770   if(pos<_ze_mesh->getNumberOfCells()-1)
9771   {
9772     MCAuto<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelfSlice(pos+1,_ze_mesh->getNumberOfCells(),true)));
9773     ms.push_back(elt);
9774   }
9775   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9776   for(std::size_t j=0;j<ms2.size();j++)
9777     ms2[j]=ms[j];
9778   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9779 }
9780
9781 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9782 {
9783   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9784 }
9785
9786 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9787 {
9788   if(pos<0)
9789     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9790   int ret(0);
9791   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9792     {
9793       if((*it).isInMyRange(pos))
9794         return ret;
9795     }
9796   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9797 }
9798
9799 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& newRight)
9800 {
9801   get(pos);//to check;
9802   if(_edge_info.empty())
9803     return ;
9804   std::size_t sz(_edge_info.size()-1);
9805   for(std::size_t i=0;i<sz;i++)
9806     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9807 }
9808
9809 const CellInfo& VectorOfCellInfo::get(int pos) const
9810 {
9811   if(pos<0 || pos>=(int)_pool.size())
9812     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9813   return _pool[pos];
9814 }
9815
9816 CellInfo& VectorOfCellInfo::get(int pos)
9817 {
9818   if(pos<0 || pos>=(int)_pool.size())
9819     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9820   return _pool[pos];
9821 }
9822
9823 /*!
9824  * Given :
9825  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9826  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9827  *
9828  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9829  *
9830  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9831  *
9832  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9833  */
9834 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MCAuto<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9835                                          MCAuto<DataArrayInt>& idsLeftRight)
9836 {
9837   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9838   if(nbCellsInSplitMesh1D==0)
9839     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9840   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9841   std::size_t nb(allEdges.size()),jj;
9842   if(nb%2!=0)
9843     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9844   std::vector<int> edge1Bis(nb*2);
9845   std::vector< MCAuto<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9846   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9847   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9848   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9849   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9850   //
9851   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9852   int *idsLeftRightPtr(idsLeftRight->getPointer());
9853   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9854   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9855     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9856       int iEnd(iStart);
9857       for(;iEnd<nbCellsInSplitMesh1D;)
9858         {
9859           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9860           if(jj!=nb)
9861             break;
9862           else
9863             iEnd++;
9864         }
9865       if(iEnd<nbCellsInSplitMesh1D)
9866         iEnd++;
9867       //
9868       MCAuto<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelfSlice(iStart,iEnd,1,true)));
9869       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9870       //
9871       MCAuto<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9872       retTmp->setCoords(splitMesh1D->getCoords());
9873       retTmp->allocateCells();
9874
9875       std::vector< std::vector<int> > out0;
9876       std::vector< std::vector< MCAuto<INTERP_KERNEL::Edge> > > out1;
9877
9878       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9879       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9880         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9881       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9882       //
9883       iStart=iEnd;
9884     }
9885   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9886     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9887   return pool.getZeMesh().retn();
9888 }
9889
9890 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9891                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9892                                      MCAuto<DataArrayInt>& idsLeftRight)
9893 {
9894   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9895   //
9896   std::vector<int> allEdges;
9897   std::vector< MCAuto<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9898   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9899     {
9900       int edgeId(std::abs(*it)-1);
9901       std::map< MCAuto<INTERP_KERNEL::Node>,int> m;
9902       MCAuto<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9903       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9904       if(*it>0)
9905         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9906       else
9907         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9908       std::size_t sz(edge1.size());
9909       for(std::size_t cnt=0;cnt<sz;cnt++)
9910         allEdgesPtr.push_back(ee);
9911     }
9912   //
9913   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9914 }
9915
9916 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9917 {
9918   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9919     {//easy case comparison not
9920       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9921     }
9922   else if(typ1.isQuadratic() && typ2.isQuadratic())
9923     {
9924       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9925       if(!status0)
9926         return false;
9927       if(conn1[2]==conn2[2])
9928         return true;
9929       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9930       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9931       return dist<eps;
9932     }
9933   else
9934     {//only one is quadratic
9935       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9936       if(!status0)
9937         return false;
9938       const double *a(0),*bb(0),*be(0);
9939       if(typ1.isQuadratic())
9940         {
9941           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9942         }
9943       else
9944         {
9945           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9946         }
9947       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9948       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9949       return dist<eps;
9950     }
9951 }
9952
9953 /*!
9954  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9955  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9956  *
9957  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9958  */
9959 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9960 {
9961   if(candidatesIn2DEnd==candidatesIn2DBg)
9962     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9963   const double *coo(mesh2DSplit->getCoords()->begin());
9964   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9965     return *candidatesIn2DBg;
9966   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9967   MCAuto<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9968   if(cellIdInMesh1DSplitRelative<0)
9969     cur1D->changeOrientationOfCells();
9970   const int *c1D(cur1D->getNodalConnectivity()->begin());
9971   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9972   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9973     {
9974       MCAuto<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9975       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9976       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9977       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9978       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9979       for(unsigned it2=0;it2<sz;it2++)
9980         {
9981           INTERP_KERNEL::NormalizedCellType typeOfSon;
9982           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9983           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9984           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9985             return *it;
9986         }
9987     }
9988   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9989 }
9990
9991 /// @endcond
9992
9993 /*!
9994  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9995  * 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
9996  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9997  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9998  *
9999  * \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
10000  *                      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)
10001  * \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
10002  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
10003  * \param [in] eps - precision used to perform intersections and localization operations.
10004  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
10005  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
10006  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
10007  *                               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.
10008  * \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
10009  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
10010  *                               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.
10011  *
10012  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
10013  */
10014 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
10015 {
10016   if(!mesh2D || !mesh1D)
10017     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
10018   mesh2D->checkFullyDefined();
10019   mesh1D->checkFullyDefined();
10020   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
10021   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
10022     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
10023   // Step 1: compute all edge intersections (new nodes)
10024   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
10025   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
10026   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10027   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10028   //
10029   // Build desc connectivity
10030   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
10031   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10032   MCAuto<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
10033   std::map<int,int> mergedNodes;
10034   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
10035   // use mergeNodes to fix intersectEdge1
10036   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
10037     {
10038       std::size_t n((*it0).size()/2);
10039       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
10040       std::map<int,int>::const_iterator it1;
10041       it1=mergedNodes.find(eltStart);
10042       if(it1!=mergedNodes.end())
10043         (*it0)[0]=(*it1).second;
10044       it1=mergedNodes.find(eltEnd);
10045       if(it1!=mergedNodes.end())
10046         (*it0)[2*n-1]=(*it1).second;
10047     }
10048   //
10049   MCAuto<DataArrayDouble> addCooDa(DataArrayDouble::New());
10050   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
10051   // Step 2: re-order newly created nodes according to the ordering found in m2
10052   std::vector< std::vector<int> > intersectEdge2;
10053   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
10054   subDiv2.clear();
10055   // Step 3: compute splitMesh1D
10056   MCAuto<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
10057   MCAuto<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
10058   MCAuto<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
10059       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
10060   MCAuto<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
10061   MCAuto<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
10062   // deal with cells in mesh2D that are not cut but only some of their edges are
10063   MCAuto<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCopy());
10064   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
10065   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
10066   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
10067   if(!idsInDesc2DToBeRefined->empty())
10068     {
10069       DataArrayInt *out0(0),*outi0(0);
10070       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
10071       MCAuto<DataArrayInt> outi0s(outi0);
10072       out0s=out0;
10073       out0s=out0s->buildUnique();
10074       out0s->sort(true);
10075     }
10076   //
10077   MCAuto<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
10078   MCAuto<DataArrayDouble> baryRet1(ret1NonCol->computeCellCenterOfMass());
10079   MCAuto<DataArrayInt> elts,eltsIndex;
10080   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
10081   MCAuto<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
10082   MCAuto<DataArrayInt> eltsIndex3(eltsIndex2->findIdsEqual(1));
10083   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
10084     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
10085   MCAuto<DataArrayInt> cellsToBeModified(elts->buildUnique());
10086   MCAuto<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
10087   if((DataArrayInt *)out0s)
10088     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
10089   std::vector< MCAuto<MEDCouplingUMesh> > outMesh2DSplit;
10090   // OK all is ready to insert in ret2 mesh
10091   if(!untouchedCells->empty())
10092     {// the most easy part, cells in mesh2D not impacted at all
10093       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
10094       outMesh2DSplit.back()->setCoords(ret1->getCoords());
10095       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
10096     }
10097   if((DataArrayInt *)out0s)
10098     {// here dealing with cells in out0s but not in cellsToBeModified
10099       MCAuto<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
10100       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
10101       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
10102         {
10103           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
10104           ret1->setCoords(outMesh2DSplit.back()->getCoords());
10105         }
10106       int offset(ret2->getNumberOfTuples());
10107       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
10108       MCAuto<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
10109       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
10110       int kk(0),*ret3ptr(partOfRet3->getPointer());
10111       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
10112         {
10113           int faceId(std::abs(*it)-1);
10114           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
10115             {
10116               int tmp(fewModifiedCells->findIdFirstEqual(*it2));
10117               if(tmp!=-1)
10118                 {
10119                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
10120                     ret3ptr[2*kk]=tmp+offset;
10121                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
10122                     ret3ptr[2*kk+1]=tmp+offset;
10123                 }
10124               else
10125                 {//the current edge is shared by a 2D cell that will be split just after
10126                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
10127                     ret3ptr[2*kk]=-(*it2+1);
10128                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
10129                     ret3ptr[2*kk+1]=-(*it2+1);
10130                 }
10131             }
10132         }
10133       m1Desc->setCoords(ret1->getCoords());
10134       ret1NonCol->setCoords(ret1->getCoords());
10135       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
10136       if(!outMesh2DSplit.empty())
10137         {
10138           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
10139           for(std::vector< MCAuto<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
10140             (*itt)->setCoords(da);
10141         }
10142     }
10143   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
10144   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
10145     {
10146       MCAuto<DataArrayInt> idsNonColPerCell(elts->findIdsEqual(*it));
10147       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
10148       MCAuto<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
10149       MCAuto<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
10150       MCAuto<DataArrayInt> partOfRet3;
10151       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));
10152       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
10153       outMesh2DSplit.push_back(splitOfOneCell);
10154       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
10155         ret2->pushBackSilent(*it);
10156     }
10157   //
10158   std::size_t nbOfMeshes(outMesh2DSplit.size());
10159   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
10160   for(std::size_t i=0;i<nbOfMeshes;i++)
10161     tmp[i]=outMesh2DSplit[i];
10162   //
10163   ret1->getCoords()->setInfoOnComponents(compNames);
10164   MCAuto<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
10165   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
10166   ret3->rearrange(1);
10167   MCAuto<DataArrayInt> edgesToDealWith(ret3->findIdsStricltyNegative());
10168   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
10169     {
10170       int old2DCellId(-ret3->getIJ(*it,0)-1);
10171       MCAuto<DataArrayInt> candidates(ret2->findIdsEqual(old2DCellId));
10172       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
10173     }
10174   ret3->changeValue(std::numeric_limits<int>::max(),-1);
10175   ret3->rearrange(2);
10176   //
10177   splitMesh1D=ret1.retn();
10178   splitMesh2D=ret2D.retn();
10179   cellIdInMesh2D=ret2.retn();
10180   cellIdInMesh1D=ret3.retn();
10181 }
10182
10183 /**
10184  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
10185  * (newly created) nodes corresponding to the edge intersections.
10186  * Output params:
10187  * @param[out] cr, crI connectivity of the resulting mesh
10188  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
10189  * TODO: describe input parameters
10190  */
10191 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
10192                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
10193                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
10194                                                          const std::vector<double>& addCoords,
10195                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
10196 {
10197   static const int SPACEDIM=2;
10198   const double *coo1(m1->getCoords()->begin());
10199   const int *conn1(m1->getNodalConnectivity()->begin()),*connI1(m1->getNodalConnectivityIndex()->begin());
10200   int offset1(m1->getNumberOfNodes());
10201   const double *coo2(m2->getCoords()->begin());
10202   const int *conn2(m2->getNodalConnectivity()->begin()),*connI2(m2->getNodalConnectivityIndex()->begin());
10203   int offset2(offset1+m2->getNumberOfNodes());
10204   int offset3(offset2+((int)addCoords.size())/2);
10205   MCAuto<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
10206   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10207   // Here a BBTree on 2D-cells, not on segments:
10208   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
10209   int ncell1(m1->getNumberOfCells());
10210   crI.push_back(0);
10211   for(int i=0;i<ncell1;i++)
10212     {
10213       std::vector<int> candidates2;
10214       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10215       std::map<INTERP_KERNEL::Node *,int> mapp;
10216       std::map<int,INTERP_KERNEL::Node *> mappRev;
10217       INTERP_KERNEL::QuadraticPolygon pol1;
10218       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
10219       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
10220       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
10221       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
10222       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
10223       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
10224           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
10225       //
10226       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
10227       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
10228       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
10229       for(it1.first();!it1.finished();it1.next())
10230         edges1.insert(it1.current()->getPtr());
10231       //
10232       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
10233       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
10234       int ii=0;
10235       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10236         {
10237           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
10238           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
10239           // Complete mapping with elements coming from the current cell it2 in mesh2:
10240           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10241           // pol2 is the new QP in the final merged result.
10242           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10243               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10244         }
10245       ii=0;
10246       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10247         {
10248           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10249           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10250           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10251           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10252         }
10253       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10254       // by m2 but that we still want to keep in the final result.
10255       if(!edges1.empty())
10256         {
10257           try
10258           {
10259               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10260           }
10261           catch(INTERP_KERNEL::Exception& e)
10262           {
10263               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();
10264               throw INTERP_KERNEL::Exception(oss.str());
10265           }
10266         }
10267       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10268         (*it).second->decrRef();
10269     }
10270 }
10271
10272 /**
10273  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10274  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10275  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10276  * The caller is to deal with the resulting DataArrayInt.
10277  *  \throw If the coordinate array is not set.
10278  *  \throw If the nodal connectivity of the cells is not defined.
10279  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10280  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10281  *
10282  * \sa DataArrayInt::sortEachPairToMakeALinkedList
10283  */
10284 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10285 {
10286   checkFullyDefined();
10287   if(getMeshDimension()!=1)
10288     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10289
10290   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10291   MCAuto<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10292   MCAuto<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10293   MCAuto<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10294   const int *d(_d->begin()), *dI(_dI->begin());
10295   const int *rD(_rD->begin()), *rDI(_rDI->begin());
10296   MCAuto<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10297   const int * dsi(_dsi->begin());
10298   MCAuto<DataArrayInt> dsii = _dsi->findIdsNotInRange(0,3);
10299   m_points=0;
10300   if (dsii->getNumberOfTuples())
10301     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10302
10303   int nc(getNumberOfCells());
10304   MCAuto<DataArrayInt> result(DataArrayInt::New());
10305   result->alloc(nc,1);
10306
10307   // set of edges not used so far
10308   std::set<int> edgeSet;
10309   for (int i=0; i<nc; edgeSet.insert(i), i++);
10310
10311   int startSeg=0;
10312   int newIdx=0;
10313   // while we have points with only one neighbor segments
10314   do
10315     {
10316       std::list<int> linePiece;
10317       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10318       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10319         {
10320           // Fill the list forward (resp. backward) from the start segment:
10321           int activeSeg = startSeg;
10322           int prevPointId = -20;
10323           int ptId;
10324           while (!edgeSet.empty())
10325             {
10326               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10327                 {
10328                   if (direction==0)
10329                     linePiece.push_back(activeSeg);
10330                   else
10331                     linePiece.push_front(activeSeg);
10332                   edgeSet.erase(activeSeg);
10333                 }
10334
10335               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10336               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10337               if (dsi[ptId] == 1) // hitting the end of the line
10338                 break;
10339               prevPointId = ptId;
10340               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10341               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10342             }
10343         }
10344       // Done, save final piece into DA:
10345       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10346       newIdx += linePiece.size();
10347
10348       // identify next valid start segment (one which is not consumed)
10349       if(!edgeSet.empty())
10350         startSeg = *(edgeSet.begin());
10351     }
10352   while (!edgeSet.empty());
10353   return result.retn();
10354 }
10355
10356 /// @cond INTERNAL
10357
10358 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MCAuto<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10359 {
10360   MCAuto<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10361   std::map<MCAuto<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10362   if(it==m.end())
10363     throw INTERP_KERNEL::Exception("Internal error in remapping !");
10364   int v((*it).second);
10365   if(v==forbVal0 || v==forbVal1)
10366     return ;
10367   if(std::find(isect.begin(),isect.end(),v)==isect.end())
10368     isect.push_back(v);
10369 }
10370
10371 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MCAuto<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10372 {
10373   int sz(c.size());
10374   if(sz<=1)
10375     return false;
10376   bool presenceOfOn(false);
10377   for(int i=0;i<sz;i++)
10378     {
10379       INTERP_KERNEL::ElementaryEdge *e(c[i]);
10380       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10381         continue ;
10382       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10383       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10384     }
10385   return presenceOfOn;
10386 }
10387
10388 /// @endcond
10389
10390 /**
10391  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10392  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10393  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10394  * a minimal creation of new nodes is wanted.
10395  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10396  * nodes if a SEG3 is split without information of middle.
10397  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10398  * avoid to have a non conform mesh.
10399  *
10400  * \return int - the number of new nodes created (in most of cases 0).
10401  * 
10402  * \throw If \a this is not coherent.
10403  * \throw If \a this has not spaceDim equal to 2.
10404  * \throw If \a this has not meshDim equal to 2.
10405  * \throw If some subcells needed to be split are orphan.
10406  * \sa MEDCouplingUMesh::conformize2D
10407  */
10408 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10409 {
10410   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10411     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10412   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10413   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10415   if(midOpt==0 && midOptI==0)
10416     {
10417       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10418       return 0;
10419     }
10420   else if(midOpt!=0 && midOptI!=0)
10421     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10422   else
10423     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10424 }
10425
10426 /*!
10427  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10428  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10429  * 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
10430  * 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).
10431  * 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.
10432  * 
10433  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10434  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10435  *
10436  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10437  * This method expects that all nodes in \a this are not closer than \a eps.
10438  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10439  * 
10440  * \param [in] eps the relative error to detect merged edges.
10441  * \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
10442  *                           that the user is expected to deal with.
10443  *
10444  * \throw If \a this is not coherent.
10445  * \throw If \a this has not spaceDim equal to 2.
10446  * \throw If \a this has not meshDim equal to 2.
10447  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10448  */
10449 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10450 {
10451   static const int SPACEDIM=2;
10452   checkConsistencyLight();
10453   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10454     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10455   MCAuto<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10456   MCAuto<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10457   const int *c(mDesc->getNodalConnectivity()->begin()),*ci(mDesc->getNodalConnectivityIndex()->begin()),*rd(revDesc1->begin()),*rdi(revDescIndx1->begin());
10458   MCAuto<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10459   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10460   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10461   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10462   std::vector<double> addCoo;
10463   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10464   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10465   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10466   for(int i=0;i<nDescCell;i++)
10467     {
10468       std::vector<int> candidates;
10469       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10470       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10471         if(*it>i)
10472           {
10473             std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
10474             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10475                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10476             INTERP_KERNEL::MergePoints merge;
10477             INTERP_KERNEL::QuadraticPolygon c1,c2;
10478             e1->intersectWith(e2,merge,c1,c2);
10479             e1->decrRef(); e2->decrRef();
10480             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10481               overlapEdge[i].push_back(*it);
10482             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10483               overlapEdge[*it].push_back(i);
10484           }
10485     }
10486   // splitting done. sort intersect point in intersectEdge.
10487   std::vector< std::vector<int> > middle(nDescCell);
10488   int nbOf2DCellsToBeSplit(0);
10489   bool middleNeedsToBeUsed(false);
10490   std::vector<bool> cells2DToTreat(nDescCell,false);
10491   for(int i=0;i<nDescCell;i++)
10492     {
10493       std::vector<int>& isect(intersectEdge[i]);
10494       int sz((int)isect.size());
10495       if(sz>1)
10496         {
10497           std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
10498           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10499           e->sortSubNodesAbs(coords,isect);
10500           e->decrRef();
10501         }
10502       if(sz!=0)
10503         {
10504           int idx0(rdi[i]),idx1(rdi[i+1]);
10505           if(idx1-idx0!=1)
10506             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10507           if(!cells2DToTreat[rd[idx0]])
10508             {
10509               cells2DToTreat[rd[idx0]]=true;
10510               nbOf2DCellsToBeSplit++;
10511             }
10512           // try to reuse at most eventual 'middle' of SEG3
10513           std::vector<int>& mid(middle[i]);
10514           mid.resize(sz+1,-1);
10515           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10516             {
10517               middleNeedsToBeUsed=true;
10518               const std::vector<int>& candidates(overlapEdge[i]);
10519               std::vector<int> trueCandidates;
10520               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10521                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10522                   trueCandidates.push_back(*itc);
10523               int stNode(c[ci[i]+1]),endNode(isect[0]);
10524               for(int j=0;j<sz+1;j++)
10525                 {
10526                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10527                     {
10528                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10529                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10530                         { mid[j]=*itc; break; }
10531                     }
10532                   stNode=endNode;
10533                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10534                 }
10535             }
10536         }
10537     }
10538   MCAuto<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10539   if(nbOf2DCellsToBeSplit==0)
10540     return ret.retn();
10541   //
10542   int *retPtr(ret->getPointer());
10543   for(int i=0;i<nCell;i++)
10544     if(cells2DToTreat[i])
10545       *retPtr++=i;
10546   //
10547   MCAuto<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10548   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10549   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10550   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10551   if(middleNeedsToBeUsed)
10552     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10553   MCAuto<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10554   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10555   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.
10556   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10557   {
10558     bool areNodesMerged; int newNbOfNodes;
10559     if(nbOfNodesCreated!=0)
10560       MCAuto<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10561   }
10562   return ret.retn();
10563 }
10564
10565 /*!
10566  * 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.
10567  * 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).
10568  * 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
10569  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10570  * 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
10571  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10572  *
10573  * 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
10574  * using new instance, idem for coordinates.
10575  *
10576  * 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.
10577  * 
10578  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10579  *
10580  * \throw If \a this is not coherent.
10581  * \throw If \a this has not spaceDim equal to 2.
10582  * \throw If \a this has not meshDim equal to 2.
10583  * 
10584  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10585  */
10586 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10587 {
10588   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10589   checkConsistencyLight();
10590   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10591     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10592   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10593   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10594   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10595   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10596   MCAuto<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10597   MCAuto<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10598   const double *coords(_coords->begin());
10599   int *newciptr(newci->getPointer());
10600   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10601     {
10602       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10603         ret->pushBackSilent(i);
10604       newciptr[1]=newc->getNumberOfTuples();
10605     }
10606   //
10607   if(ret->empty())
10608     return ret.retn();
10609   if(!appendedCoords->empty())
10610     {
10611       appendedCoords->rearrange(2);
10612       MCAuto<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10613       //non const part
10614       setCoords(newCoords);
10615     }
10616   //non const part
10617   setConnectivity(newc,newci,true);
10618   return ret.retn();
10619 }
10620
10621 /*!
10622  * \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.
10623  *                               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.
10624  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10625  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10626  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10627  * \param [out] addCoo - nodes to be append at the end
10628  * \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.
10629  */
10630 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10631                                          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)
10632 {
10633   static const int SPACEDIM=2;
10634   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10635   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10636   const int *c1(m1Desc->getNodalConnectivity()->begin()),*ci1(m1Desc->getNodalConnectivityIndex()->begin());
10637   // Build BB tree of all edges in the tool mesh (second mesh)
10638   MCAuto<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10639   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10640   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10641   intersectEdge1.resize(nDescCell1);
10642   colinear2.resize(nDescCell2);
10643   subDiv2.resize(nDescCell2);
10644   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10645
10646   std::vector<int> candidates1(1);
10647   int offset1(m1Desc->getNumberOfNodes());
10648   int offset2(offset1+m2Desc->getNumberOfNodes());
10649   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10650     {
10651       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10652       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10653       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10654         {
10655           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10656           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10657           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10658           candidates1[0]=i;
10659           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10660           // 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
10661           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10662           std::set<INTERP_KERNEL::Node *> nodes;
10663           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10664           std::size_t szz(nodes.size());
10665           std::vector< MCAuto<INTERP_KERNEL::Node> > nodesSafe(szz);
10666           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10667           for(std::size_t iii=0;iii<szz;iii++,itt++)
10668             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10669           // end of protection
10670           // Performs egde cutting:
10671           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10672           delete pol2;
10673           delete pol1;
10674         }
10675       else
10676         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10677         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10678     }
10679 }
10680
10681 /*!
10682  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10683  * It builds the descending connectivity of the two meshes, and then using a binary tree
10684  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10685  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10686  */
10687 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10688                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10689                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10690                                                    std::vector<double>& addCoo,
10691                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10692 {
10693   // Build desc connectivity
10694   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10695   desc2=DataArrayInt::New();
10696   descIndx2=DataArrayInt::New();
10697   revDesc2=DataArrayInt::New();
10698   revDescIndx2=DataArrayInt::New();
10699   MCAuto<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10700   MCAuto<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10701   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10702   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10703   MCAuto<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10704   std::map<int,int> notUsedMap;
10705   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10706   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10707   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10708 }
10709
10710 /*!
10711  * This method performs the 2nd step of Partition of 2D mesh.
10712  * This method has 4 inputs :
10713  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10714  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10715  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10716  * 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'
10717  * Nodes end up lying consecutively on a cutted edge.
10718  * \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.
10719  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10720  * \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.
10721  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10722  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10723  */
10724 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10725                                            const std::vector<double>& addCoo,
10726                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10727 {
10728   int offset1=m1->getNumberOfNodes();
10729   int ncell=m2->getNumberOfCells();
10730   const int *c=m2->getNodalConnectivity()->begin();
10731   const int *cI=m2->getNodalConnectivityIndex()->begin();
10732   const double *coo=m2->getCoords()->begin();
10733   const double *cooBis=m1->getCoords()->begin();
10734   int offset2=offset1+m2->getNumberOfNodes();
10735   intersectEdge.resize(ncell);
10736   for(int i=0;i<ncell;i++,cI++)
10737     {
10738       const std::vector<int>& divs=subDiv[i];
10739       int nnode=cI[1]-cI[0]-1;
10740       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10741       std::map<INTERP_KERNEL::Node *, int> mapp22;
10742       for(int j=0;j<nnode;j++)
10743         {
10744           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10745           int nnid=c[(*cI)+j+1];
10746           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10747           mapp22[nn]=nnid+offset1;
10748         }
10749       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10750       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10751         ((*it).second.first)->decrRef();
10752       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10753       std::map<INTERP_KERNEL::Node *,int> mapp3;
10754       for(std::size_t j=0;j<divs.size();j++)
10755         {
10756           int id=divs[j];
10757           INTERP_KERNEL::Node *tmp=0;
10758           if(id<offset1)
10759             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10760           else if(id<offset2)
10761             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10762           else
10763             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10764           addNodes[j]=tmp;
10765           mapp3[tmp]=id;
10766         }
10767       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10768       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10769         (*it)->decrRef();
10770       e->decrRef();
10771     }
10772 }
10773
10774 /*!
10775  * 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).
10776  * 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
10777  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10778  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10779  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10780  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10781  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10782  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10783  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10784  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10785  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10786  * \param [out] cut3DSuf input/output param.
10787  */
10788 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10789                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10790                                                    const int *desc, const int *descIndx, 
10791                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10792 {
10793   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10794   int nbOf3DSurfCell=(int)cut3DSurf.size();
10795   for(int i=0;i<nbOf3DSurfCell;i++)
10796     {
10797       std::vector<int> res;
10798       int offset=descIndx[i];
10799       int nbOfSeg=descIndx[i+1]-offset;
10800       for(int j=0;j<nbOfSeg;j++)
10801         {
10802           int edgeId=desc[offset+j];
10803           int status=cut3DCurve[edgeId];
10804           if(status!=-2)
10805             {
10806               if(status>-1)
10807                 res.push_back(status);
10808               else
10809                 {
10810                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10811                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10812                 }
10813             }
10814         }
10815       switch(res.size())
10816       {
10817         case 2:
10818           {
10819             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10820             break;
10821           }
10822         case 1:
10823         case 0:
10824           {
10825             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10826             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10827             if(res.size()==2)
10828               {
10829                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10830               }
10831             else
10832               {
10833                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10834               }
10835             break;
10836           }
10837         default:
10838           {// case when plane is on a multi colinear edge of a polyhedron
10839             if((int)res.size()==2*nbOfSeg)
10840               {
10841                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10842               }
10843             else
10844               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10845           }
10846       }
10847     }
10848 }
10849
10850 /*!
10851  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10852  * 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).
10853  * 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
10854  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10855  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10856  * \param desc is the descending connectivity 3D->3DSurf
10857  * \param descIndx is the descending connectivity index 3D->3DSurf
10858  */
10859 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10860                                                   const int *desc, const int *descIndx,
10861                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10862 {
10863   checkFullyDefined();
10864   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10865     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10866   const int *nodal3D(_nodal_connec->begin()),*nodalIndx3D(_nodal_connec_index->begin());
10867   int nbOfCells(getNumberOfCells());
10868   for(int i=0;i<nbOfCells;i++)
10869     {
10870       std::map<int, std::set<int> > m;
10871       int offset=descIndx[i];
10872       int nbOfFaces=descIndx[i+1]-offset;
10873       int start=-1;
10874       int end=-1;
10875       for(int j=0;j<nbOfFaces;j++)
10876         {
10877           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10878           if(p.first!=-1 && p.second!=-1)
10879             {
10880               if(p.first!=-2)
10881                 {
10882                   start=p.first; end=p.second;
10883                   m[p.first].insert(p.second);
10884                   m[p.second].insert(p.first);
10885                 }
10886               else
10887                 {
10888                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10889                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10890                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10891                   INTERP_KERNEL::NormalizedCellType cmsId;
10892                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10893                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10894                   for(unsigned k=0;k<nbOfNodesSon;k++)
10895                     {
10896                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10897                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10898                     }
10899                 }
10900             }
10901         }
10902       if(m.empty())
10903         continue;
10904       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10905       int prev=end;
10906       while(end!=start)
10907         {
10908           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10909           const std::set<int>& s=(*it).second;
10910           std::set<int> s2; s2.insert(prev);
10911           std::set<int> s3;
10912           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10913           if(s3.size()==1)
10914             {
10915               int val=*s3.begin();
10916               conn.push_back(start);
10917               prev=start;
10918               start=val;
10919             }
10920           else
10921             start=end;
10922         }
10923       conn.push_back(end);
10924       if(conn.size()>3)
10925         {
10926           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10927           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10928           cellIds->pushBackSilent(i);
10929         }
10930     }
10931 }
10932
10933 void InsertNodeInConnIfNecessary(int nodeIdToInsert, std::vector<int>& conn, const double *coords, double eps)
10934 {
10935   std::vector<int>::iterator it(std::find(conn.begin(),conn.end(),nodeIdToInsert));
10936   if(it!=conn.end())
10937     return ;
10938   std::size_t sz(conn.size());
10939   std::size_t found(std::numeric_limits<std::size_t>::max());
10940   for(std::size_t i=0;i<sz;i++)
10941     {
10942       int pt0(conn[i]),pt1(conn[(i+1)%sz]);
10943       double v1[3]={coords[3*pt1+0]-coords[3*pt0+0],coords[3*pt1+1]-coords[3*pt0+1],coords[3*pt1+2]-coords[3*pt0+2]},v2[3]={coords[3*nodeIdToInsert+0]-coords[3*pt0+0],coords[3*nodeIdToInsert+1]-coords[3*pt0+1],coords[3*nodeIdToInsert+2]-coords[3*pt0+2]};
10944       double normm(sqrt(v1[0]*v1[0]+v1[1]*v1[1]+v1[2]*v1[2]));
10945       std::transform(v1,v1+3,v1,std::bind2nd(std::multiplies<double>(),1./normm));
10946       std::transform(v2,v2+3,v2,std::bind2nd(std::multiplies<double>(),1./normm));
10947       double v3[3];
10948       v3[0]=v1[1]*v2[2]-v1[2]*v2[1]; v3[1]=v1[2]*v2[0]-v1[0]*v2[2]; v3[2]=v1[0]*v2[1]-v1[1]*v2[0];
10949       double normm2(sqrt(v3[0]*v3[0]+v3[1]*v3[1]+v3[2]*v3[2])),dotTest(v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]);
10950       if(normm2<eps)
10951         if(dotTest>eps && dotTest<1.-eps)
10952           {
10953             found=i;
10954             break;
10955           }
10956     }
10957   if(found==std::numeric_limits<std::size_t>::max())
10958     throw INTERP_KERNEL::Exception("InsertNodeInConnIfNecessary : not found point !");
10959   conn.insert(conn.begin()+(found+1)%sz,nodeIdToInsert);
10960 }
10961
10962 void SplitIntoToPart(const std::vector<int>& conn, int pt0, int pt1, std::vector<int>& part0, std::vector<int>& part1)
10963 {
10964   std::size_t sz(conn.size());
10965   std::vector<int> *curPart(&part0);
10966   for(std::size_t i=0;i<sz;i++)
10967     {
10968       int nextt(conn[(i+1)%sz]);
10969       (*curPart).push_back(nextt);
10970       if(nextt==pt0 || nextt==pt1)
10971         {
10972           if(curPart==&part0)
10973             curPart=&part1;
10974           else
10975             curPart=&part0;
10976           (*curPart).push_back(nextt);
10977         }
10978     }
10979 }
10980
10981 /*!
10982  * this method method splits cur cells 3D Surf in sub cells 3DSurf using the previous subsplit. This method is the last one used to clip.
10983  */
10984 void MEDCouplingUMesh::buildSubCellsFromCut(const std::vector< std::pair<int,int> >& cut3DSurf,
10985                                             const int *desc, const int *descIndx, const double *coords, double eps,
10986                                             std::vector<std::vector<int> >& res) const
10987 {
10988   checkFullyDefined();
10989   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10990     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSubCellsFromCut works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10991   const int *nodal3D(_nodal_connec->begin()),*nodalIndx3D(_nodal_connec_index->begin());
10992   int nbOfCells(getNumberOfCells());
10993   if(nbOfCells!=1)
10994     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSubCellsFromCut works only with single cell presently !");
10995   for(int i=0;i<nbOfCells;i++)
10996     {
10997       int offset(descIndx[i]),nbOfFaces(descIndx[i+1]-offset),start(-1),end(-1);
10998       for(int j=0;j<nbOfFaces;j++)
10999         {
11000           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
11001           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]));
11002           int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
11003           INTERP_KERNEL::AutoPtr<int> tmp(new int[sz]);
11004           INTERP_KERNEL::NormalizedCellType cmsId;
11005           unsigned nbOfNodesSon(cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId));
11006           std::vector<int> elt((int *)tmp,(int *)tmp+nbOfNodesSon);
11007           if(p.first!=-1 && p.second!=-1)
11008             {
11009               if(p.first!=-2)
11010                 {
11011                   InsertNodeInConnIfNecessary(p.first,elt,coords,eps);
11012                   InsertNodeInConnIfNecessary(p.second,elt,coords,eps);
11013                   std::vector<int> elt1,elt2;
11014                   SplitIntoToPart(elt,p.first,p.second,elt1,elt2);
11015                   res.push_back(elt1);
11016                   res.push_back(elt2);
11017                 }
11018               else
11019                 res.push_back(elt);
11020             }
11021           else
11022             res.push_back(elt);
11023         }
11024     }
11025 }
11026
11027 /*!
11028  * 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
11029  * 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
11030  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
11031  * 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
11032  * 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.
11033  * 
11034  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
11035  */
11036 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
11037 {
11038   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
11039   if(sz>=4)
11040     {
11041       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
11042       if(cm.getDimension()==2)
11043         {
11044           const int *node=nodalConnBg+1;
11045           int startNode=*node++;
11046           double refX=coords[2*startNode];
11047           for(;node!=nodalConnEnd;node++)
11048             {
11049               if(coords[2*(*node)]<refX)
11050                 {
11051                   startNode=*node;
11052                   refX=coords[2*startNode];
11053                 }
11054             }
11055           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
11056           refX=1e300;
11057           double tmp1;
11058           double tmp2[2];
11059           double angle0=-M_PI/2;
11060           //
11061           int nextNode=-1;
11062           int prevNode=-1;
11063           double resRef;
11064           double angleNext=0.;
11065           while(nextNode!=startNode)
11066             {
11067               nextNode=-1;
11068               resRef=1e300;
11069               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
11070                 {
11071                   if(*node!=tmpOut.back() && *node!=prevNode)
11072                     {
11073                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
11074                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
11075                       double res;
11076                       if(angleM<=angle0)
11077                         res=angle0-angleM;
11078                       else
11079                         res=angle0-angleM+2.*M_PI;
11080                       if(res<resRef)
11081                         {
11082                           nextNode=*node;
11083                           resRef=res;
11084                           angleNext=angleM;
11085                         }
11086                     }
11087                 }
11088               if(nextNode!=startNode)
11089                 {
11090                   angle0=angleNext-M_PI;
11091                   if(angle0<-M_PI)
11092                     angle0+=2*M_PI;
11093                   prevNode=tmpOut.back();
11094                   tmpOut.push_back(nextNode);
11095                 }
11096             }
11097           std::vector<int> tmp3(2*(sz-1));
11098           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
11099           std::copy(nodalConnBg+1,nodalConnEnd,it);
11100           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
11101             {
11102               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
11103               return false;
11104             }
11105           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
11106             {
11107               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
11108               return false;
11109             }
11110           else
11111             {
11112               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
11113               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
11114               return true;
11115             }
11116         }
11117       else
11118         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
11119     }
11120   else
11121     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
11122 }
11123
11124 /*!
11125  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
11126  * 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.
11127  * 
11128  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
11129  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
11130  * \param [in,out] arr array in which the remove operation will be done.
11131  * \param [in,out] arrIndx array in the remove operation will modify
11132  * \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])
11133  * \return true if \b arr and \b arrIndx have been modified, false if not.
11134  */
11135 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
11136 {
11137   if(!arrIndx || !arr)
11138     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
11139   if(offsetForRemoval<0)
11140     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
11141   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
11142   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
11143   int *arrIPtr=arrIndx->getPointer();
11144   *arrIPtr++=0;
11145   int previousArrI=0;
11146   const int *arrPtr=arr->begin();
11147   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
11148   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
11149     {
11150       if(*arrIPtr-previousArrI>offsetForRemoval)
11151         {
11152           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
11153             {
11154               if(s.find(*work)==s.end())
11155                 arrOut.push_back(*work);
11156             }
11157         }
11158       previousArrI=*arrIPtr;
11159       *arrIPtr=(int)arrOut.size();
11160     }
11161   if(arr->getNumberOfTuples()==(int)arrOut.size())
11162     return false;
11163   arr->alloc((int)arrOut.size(),1);
11164   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
11165   return true;
11166 }
11167
11168 /*!
11169  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
11170  * (\ref numbering-indirect).
11171  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
11172  * The selection of extraction is done standardly in new2old format.
11173  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
11174  *
11175  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11176  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11177  * \param [in] arrIn arr origin array from which the extraction will be done.
11178  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11179  * \param [out] arrOut the resulting array
11180  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11181  * \sa MEDCouplingUMesh::ExtractFromIndexedArraysSlice
11182  */
11183 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11184                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11185 {
11186   if(!arrIn || !arrIndxIn)
11187     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
11188   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
11189   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
11190     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
11191   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
11192   const int *arrInPtr=arrIn->begin();
11193   const int *arrIndxPtr=arrIndxIn->begin();
11194   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
11195   if(nbOfGrps<0)
11196     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
11197   int maxSizeOfArr=arrIn->getNumberOfTuples();
11198   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11199   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11200   arrIo->alloc((int)(sz+1),1);
11201   const int *idsIt=idsOfSelectBg;
11202   int *work=arrIo->getPointer();
11203   *work++=0;
11204   int lgth=0;
11205   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
11206     {
11207       if(*idsIt>=0 && *idsIt<nbOfGrps)
11208         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
11209       else
11210         {
11211           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
11212           throw INTERP_KERNEL::Exception(oss.str());
11213         }
11214       if(lgth>=work[-1])
11215         *work=lgth;
11216       else
11217         {
11218           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
11219           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
11220           throw INTERP_KERNEL::Exception(oss.str());
11221         }
11222     }
11223   arro->alloc(lgth,1);
11224   work=arro->getPointer();
11225   idsIt=idsOfSelectBg;
11226   for(std::size_t i=0;i<sz;i++,idsIt++)
11227     {
11228       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
11229         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
11230       else
11231         {
11232           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
11233           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
11234           throw INTERP_KERNEL::Exception(oss.str());
11235         }
11236     }
11237   arrOut=arro.retn();
11238   arrIndexOut=arrIo.retn();
11239 }
11240
11241 /*!
11242  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
11243  * (\ref numbering-indirect).
11244  * 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 ).
11245  * The selection of extraction is done standardly in new2old format.
11246  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
11247  *
11248  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
11249  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
11250  * \param [in] idsOfSelectStep
11251  * \param [in] arrIn arr origin array from which the extraction will be done.
11252  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11253  * \param [out] arrOut the resulting array
11254  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11255  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
11256  */
11257 void MEDCouplingUMesh::ExtractFromIndexedArraysSlice(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11258                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11259 {
11260   if(!arrIn || !arrIndxIn)
11261     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input pointer is NULL !");
11262   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
11263   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
11264     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : input arrays must have exactly one component !");
11265   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArraysSlice : Input slice ");
11266   const int *arrInPtr=arrIn->begin();
11267   const int *arrIndxPtr=arrIndxIn->begin();
11268   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
11269   if(nbOfGrps<0)
11270     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArraysSlice : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
11271   int maxSizeOfArr=arrIn->getNumberOfTuples();
11272   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11273   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11274   arrIo->alloc((int)(sz+1),1);
11275   int idsIt=idsOfSelectStart;
11276   int *work=arrIo->getPointer();
11277   *work++=0;
11278   int lgth=0;
11279   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
11280     {
11281       if(idsIt>=0 && idsIt<nbOfGrps)
11282         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
11283       else
11284         {
11285           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
11286           throw INTERP_KERNEL::Exception(oss.str());
11287         }
11288       if(lgth>=work[-1])
11289         *work=lgth;
11290       else
11291         {
11292           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
11293           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
11294           throw INTERP_KERNEL::Exception(oss.str());
11295         }
11296     }
11297   arro->alloc(lgth,1);
11298   work=arro->getPointer();
11299   idsIt=idsOfSelectStart;
11300   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
11301     {
11302       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
11303         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
11304       else
11305         {
11306           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArraysSlice : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
11307           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
11308           throw INTERP_KERNEL::Exception(oss.str());
11309         }
11310     }
11311   arrOut=arro.retn();
11312   arrIndexOut=arrIo.retn();
11313 }
11314
11315 /*!
11316  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11317  * 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
11318  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11319  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11320  *
11321  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11322  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11323  * \param [in] arrIn arr origin array from which the extraction will be done.
11324  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11325  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
11326  * \param [in] srcArrIndex index array of \b srcArr
11327  * \param [out] arrOut the resulting array
11328  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11329  * 
11330  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11331  */
11332 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11333                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11334                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11335 {
11336   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11337     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11338   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11339   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11340   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11341   std::vector<bool> v(nbOfTuples,true);
11342   int offset=0;
11343   const int *arrIndxInPtr=arrIndxIn->begin();
11344   const int *srcArrIndexPtr=srcArrIndex->begin();
11345   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11346     {
11347       if(*it>=0 && *it<nbOfTuples)
11348         {
11349           v[*it]=false;
11350           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11351         }
11352       else
11353         {
11354           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11355           throw INTERP_KERNEL::Exception(oss.str());
11356         }
11357     }
11358   srcArrIndexPtr=srcArrIndex->begin();
11359   arrIo->alloc(nbOfTuples+1,1);
11360   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11361   const int *arrInPtr=arrIn->begin();
11362   const int *srcArrPtr=srcArr->begin();
11363   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11364   int *arroPtr=arro->getPointer();
11365   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11366     {
11367       if(v[ii])
11368         {
11369           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11370           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11371         }
11372       else
11373         {
11374           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11375           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11376           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11377         }
11378     }
11379   arrOut=arro.retn();
11380   arrIndexOut=arrIo.retn();
11381 }
11382
11383 /*!
11384  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11385  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11386  *
11387  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11388  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11389  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11390  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11391  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11392  * \param [in] srcArrIndex index array of \b srcArr
11393  * 
11394  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11395  */
11396 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11397                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11398 {
11399   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11400     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11401   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11402   const int *arrIndxInPtr=arrIndxIn->begin();
11403   const int *srcArrIndexPtr=srcArrIndex->begin();
11404   int *arrInOutPtr=arrInOut->getPointer();
11405   const int *srcArrPtr=srcArr->begin();
11406   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11407     {
11408       if(*it>=0 && *it<nbOfTuples)
11409         {
11410           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11411             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11412           else
11413             {
11414               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] !";
11415               throw INTERP_KERNEL::Exception(oss.str());
11416             }
11417         }
11418       else
11419         {
11420           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11421           throw INTERP_KERNEL::Exception(oss.str());
11422         }
11423     }
11424 }
11425
11426 /*!
11427  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11428  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11429  * 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]].
11430  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11431  * A negative value in \b arrIn means that it is ignored.
11432  * 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.
11433  * 
11434  * \param [in] arrIn arr origin array from which the extraction will be done.
11435  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11436  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11437  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11438  */
11439 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11440 {
11441   int seed=0,nbOfDepthPeelingPerformed=0;
11442   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11443 }
11444
11445 /*!
11446  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11447  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11448  * 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]].
11449  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11450  * A negative value in \b arrIn means that it is ignored.
11451  * 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.
11452  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11453  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11454  * \param [in] arrIn arr origin array from which the extraction will be done.
11455  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11456  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11457  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11458  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11459  * \sa MEDCouplingUMesh::partitionBySpreadZone
11460  */
11461 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11462 {
11463   nbOfDepthPeelingPerformed=0;
11464   if(!arrIndxIn)
11465     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11466   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11467   if(nbOfTuples<=0)
11468     {
11469       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11470       return ret;
11471     }
11472   //
11473   std::vector<bool> fetched(nbOfTuples,false);
11474   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11475 }
11476
11477 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11478 {
11479   nbOfDepthPeelingPerformed=0;
11480   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11481     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11482   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11483   std::vector<bool> fetched2(nbOfTuples,false);
11484   int i=0;
11485   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11486     {
11487       if(*seedElt>=0 && *seedElt<nbOfTuples)
11488         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11489       else
11490         { 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()); }
11491     }
11492   const int *arrInPtr=arrIn->begin();
11493   const int *arrIndxPtr=arrIndxIn->begin();
11494   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11495   std::vector<int> idsToFetch1(seedBg,seedEnd);
11496   std::vector<int> idsToFetch2;
11497   std::vector<int> *idsToFetch=&idsToFetch1;
11498   std::vector<int> *idsToFetchOther=&idsToFetch2;
11499   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11500     {
11501       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11502         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11503           if(!fetched[*it2])
11504             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11505       std::swap(idsToFetch,idsToFetchOther);
11506       idsToFetchOther->clear();
11507       nbOfDepthPeelingPerformed++;
11508     }
11509   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11510   i=0;
11511   MCAuto<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11512   int *retPtr=ret->getPointer();
11513   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11514     if(*it)
11515       *retPtr++=i;
11516   return ret.retn();
11517 }
11518
11519 /*!
11520  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11521  * 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
11522  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11523  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11524  *
11525  * \param [in] start begin of set of ids of the input extraction (included)
11526  * \param [in] end end of set of ids of the input extraction (excluded)
11527  * \param [in] step step of the set of ids in range mode.
11528  * \param [in] arrIn arr origin array from which the extraction will be done.
11529  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11530  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11531  * \param [in] srcArrIndex index array of \b srcArr
11532  * \param [out] arrOut the resulting array
11533  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11534  * 
11535  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11536  */
11537 void MEDCouplingUMesh::SetPartOfIndexedArraysSlice(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11538                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11539                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11540 {
11541   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11542     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSlice : presence of null pointer in input parameter !");
11543   MCAuto<DataArrayInt> arro=DataArrayInt::New();
11544   MCAuto<DataArrayInt> arrIo=DataArrayInt::New();
11545   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11546   int offset=0;
11547   const int *arrIndxInPtr=arrIndxIn->begin();
11548   const int *srcArrIndexPtr=srcArrIndex->begin();
11549   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSlice : ");
11550   int it=start;
11551   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11552     {
11553       if(it>=0 && it<nbOfTuples)
11554         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11555       else
11556         {
11557           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11558           throw INTERP_KERNEL::Exception(oss.str());
11559         }
11560     }
11561   srcArrIndexPtr=srcArrIndex->begin();
11562   arrIo->alloc(nbOfTuples+1,1);
11563   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11564   const int *arrInPtr=arrIn->begin();
11565   const int *srcArrPtr=srcArr->begin();
11566   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11567   int *arroPtr=arro->getPointer();
11568   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11569     {
11570       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11571       if(pos<0)
11572         {
11573           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11574           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11575         }
11576       else
11577         {
11578           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11579           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11580         }
11581     }
11582   arrOut=arro.retn();
11583   arrIndexOut=arrIo.retn();
11584 }
11585
11586 /*!
11587  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11588  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11589  *
11590  * \param [in] start begin of set of ids of the input extraction (included)
11591  * \param [in] end end of set of ids of the input extraction (excluded)
11592  * \param [in] step step of the set of ids in range mode.
11593  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11594  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11595  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11596  * \param [in] srcArrIndex index array of \b srcArr
11597  * 
11598  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSlice MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11599  */
11600 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11601                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11602 {
11603   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11604     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : presence of null pointer in input parameter !");
11605   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11606   const int *arrIndxInPtr=arrIndxIn->begin();
11607   const int *srcArrIndexPtr=srcArrIndex->begin();
11608   int *arrInOutPtr=arrInOut->getPointer();
11609   const int *srcArrPtr=srcArr->begin();
11610   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : ");
11611   int it=start;
11612   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11613     {
11614       if(it>=0 && it<nbOfTuples)
11615         {
11616           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11617             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11618           else
11619             {
11620               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11621               throw INTERP_KERNEL::Exception(oss.str());
11622             }
11623         }
11624       else
11625         {
11626           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdxSlice : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11627           throw INTERP_KERNEL::Exception(oss.str());
11628         }
11629     }
11630 }
11631
11632 /*!
11633  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11634  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11635  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11636  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11637  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11638  * 
11639  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11640  */
11641 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11642 {
11643   checkFullyDefined();
11644   int mdim=getMeshDimension();
11645   int spaceDim=getSpaceDimension();
11646   if(mdim!=spaceDim)
11647     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11648   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11649   std::vector< MCAuto<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11650   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MCAuto<DataArrayInt> > >(partitionAuto));
11651   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11652   ret->setCoords(getCoords());
11653   ret->allocateCells((int)partition.size());
11654   //
11655   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11656     {
11657       MCAuto<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11658       MCAuto<DataArrayInt> cell;
11659       switch(mdim)
11660       {
11661         case 2:
11662           cell=tmp->buildUnionOf2DMesh();
11663           break;
11664         case 3:
11665           cell=tmp->buildUnionOf3DMesh();
11666           break;
11667         default:
11668           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11669       }
11670
11671       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->begin()+1);
11672     }
11673   //
11674   ret->finishInsertingCells();
11675   return ret.retn();
11676 }
11677
11678 /*!
11679  * This method partitions \b this into contiguous zone.
11680  * This method only needs a well defined connectivity. Coordinates are not considered here.
11681  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11682  */
11683 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11684 {
11685   DataArrayInt *neigh=0,*neighI=0;
11686   computeNeighborsOfCells(neigh,neighI);
11687   MCAuto<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11688   return PartitionBySpreadZone(neighAuto,neighIAuto);
11689 }
11690
11691 std::vector<DataArrayInt *> MEDCouplingUMesh::PartitionBySpreadZone(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11692 {
11693   if(!arrIn || !arrIndxIn)
11694     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : null input pointers !");
11695   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
11696   int nbOfTuples(arrIndxIn->getNumberOfTuples());
11697   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1 || nbOfTuples<1)
11698     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : invalid arrays in input !");
11699   int nbOfCellsCur(nbOfTuples-1);
11700   std::vector<DataArrayInt *> ret;
11701   if(nbOfCellsCur<=0)
11702     return ret;
11703   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11704   std::vector< MCAuto<DataArrayInt> > ret2;
11705   int seed=0;
11706   while(seed<nbOfCellsCur)
11707     {
11708       int nbOfPeelPerformed=0;
11709       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfPeelPerformed));
11710       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11711     }
11712   for(std::vector< MCAuto<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11713     ret.push_back((*it).retn());
11714   return ret;
11715 }
11716
11717 /*!
11718  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11719  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11720  *
11721  * \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.
11722  * \return a newly allocated DataArrayInt to be managed by the caller.
11723  * \throw In case of \a code has not the right format (typically of size 3*n)
11724  */
11725 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11726 {
11727   MCAuto<DataArrayInt> ret=DataArrayInt::New();
11728   std::size_t nb=code.size()/3;
11729   if(code.size()%3!=0)
11730     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11731   ret->alloc((int)nb,2);
11732   int *retPtr=ret->getPointer();
11733   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11734     {
11735       retPtr[0]=code[3*i+2];
11736       retPtr[1]=code[3*i+2]+code[3*i+1];
11737     }
11738   return ret.retn();
11739 }
11740
11741 /*!
11742  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11743  * All cells in \a this are expected to be linear 3D cells.
11744  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11745  * It leads to an increase to number of cells.
11746  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11747  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11748  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11749  *
11750  * \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.
11751  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11752  * \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. 
11753  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11754  *          an id of old cell producing it. The caller is to delete this array using
11755  *         decrRef() as it is no more needed.
11756  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11757  *
11758  * \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
11759  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11760  * 
11761  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11762  * \throw If \a this is not fully constituted with linear 3D cells.
11763  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11764  */
11765 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11766 {
11767   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11768   checkConnectivityFullyDefined();
11769   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11770     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11771   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11772   MCAuto<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11773   MCAuto<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11774   int *retPt(ret->getPointer());
11775   MCAuto<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11776   MCAuto<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11777   const int *oldc(_nodal_connec->begin());
11778   const int *oldci(_nodal_connec_index->begin());
11779   const double *coords(_coords->begin());
11780   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11781     {
11782       std::vector<int> a; std::vector<double> b;
11783       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11784       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11785       const int *aa(&a[0]);
11786       if(!b.empty())
11787         {
11788           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11789             if(*it<0)
11790               *it=(-(*(it))-1+nbNodes);
11791           addPts->insertAtTheEnd(b.begin(),b.end());
11792           nbNodes+=(int)b.size()/3;
11793         }
11794       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11795         newConn->insertAtTheEnd(aa,aa+4);
11796     }
11797   if(!addPts->empty())
11798     {
11799       addPts->rearrange(3);
11800       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11801       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11802       ret0->setCoords(addPts);
11803     }
11804   else
11805     {
11806       nbOfAdditionalPoints=0;
11807       ret0->setCoords(getCoords());
11808     }
11809   ret0->setNodalConnectivity(newConn);
11810   //
11811   ret->computeOffsetsFull();
11812   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11813   return ret0.retn();
11814 }
11815
11816 /*!
11817  * 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). 
11818  *
11819  * \sa MEDCouplingUMesh::split2DCells
11820  */
11821 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11822 {
11823   checkConnectivityFullyDefined();
11824   int ncells(getNumberOfCells()),lgthToReach(getNodalConnectivityArrayLen()+subNodesInSeg->getNumberOfTuples());
11825   MCAuto<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11826   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11827   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11828   int prevPosOfCi(ciPtr[0]);
11829   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11830     {
11831       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11832       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11833       for(int j=0;j<sz;j++)
11834         {
11835           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11836           for(int k=0;k<sz2;k++)
11837             *cPtr++=subPtr[offset2+k];
11838           if(j!=sz-1)
11839             *cPtr++=oldConn[prevPosOfCi+j+2];
11840           deltaSz+=sz2;
11841         }
11842       prevPosOfCi=ciPtr[1];
11843       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11844     }
11845   if(c->end()!=cPtr)
11846     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11847   _nodal_connec->decrRef();
11848   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11849 }
11850
11851 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11852 {
11853   if(id!=-1)
11854     return id;
11855   else
11856     {
11857       int ret(nodesCnter++);
11858       double newPt[2];
11859       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11860       addCoo.insertAtTheEnd(newPt,newPt+2);
11861       return ret;
11862     }
11863 }
11864
11865 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11866 {
11867   if(id!=-1)
11868     return id;
11869   else
11870     {
11871       int ret(nodesCnter++);
11872       double newPt[2];
11873       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11874       addCoo.insertAtTheEnd(newPt,newPt+2);
11875       return ret;
11876     }
11877 }
11878
11879
11880 /// @cond INTERNAL
11881
11882 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)
11883 {
11884   int tmp[3];
11885   int trueStart(start>=0?start:nbOfEdges+start);
11886   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11887   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11888   if(linOrArc)
11889     {
11890       if(stp-start>1)
11891         {
11892           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11893           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11894           middles.push_back(tmp3+offset);
11895         }
11896       else
11897         middles.push_back(connBg[trueStart+nbOfEdges]);
11898     }
11899 }
11900
11901 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)
11902 {
11903   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11904   newConnOfCell->pushBackSilent(tmpEnd);
11905   if(linOrArc)
11906     {
11907       if(stp-start>1)
11908         {
11909           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11910           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11911           middles.push_back(tmp3+offset);
11912         }
11913       else
11914         middles.push_back(connBg[start+nbOfEdges]);
11915     }
11916 }
11917
11918 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)
11919 {
11920   // only the quadratic point to deal with:
11921   if(linOrArc)
11922     {
11923       if(stp-start>1)
11924         {
11925           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11926           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11927           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11928           middles.push_back(tmp3+offset);
11929         }
11930       else
11931         middles.push_back(connBg[start+nbOfEdges]);
11932     }
11933 }
11934
11935 /// @endcond
11936
11937 /*!
11938  * 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 ) .
11939  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11940  */
11941 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11942 {
11943   std::size_t sz(std::distance(connBg,connEnd));
11944   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11945     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11946   sz--;
11947   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11948   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11949   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11950   unsigned nbOfHit(0); // number of fusions operated
11951   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11952   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
11953   INTERP_KERNEL::NormalizedCellType typeOfSon;
11954   std::vector<int> middles;
11955   bool ret(false);
11956   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11957     {
11958       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11959       std::map<MCAuto<INTERP_KERNEL::Node>,int> m;
11960       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11961       posEndElt = posBaseElt+1;
11962
11963       // Look backward first: are the final edges of the cells colinear with the first ones?
11964       // This initializes posBaseElt.
11965       if(nbOfTurn==0)
11966         {
11967           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11968             {
11969               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11970               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11971               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11972               bool isColinear=eint->areColinears();
11973               if(isColinear)
11974                 {
11975                   nbOfHit++;
11976                   posBaseElt--;
11977                   ret=true;
11978                 }
11979               delete eint;
11980               eCand->decrRef();
11981               if(!isColinear)
11982                 break;
11983             }
11984         }
11985       // Now move forward:
11986       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11987       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11988         {
11989           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11990           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11991           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11992           bool isColinear(eint->areColinears());
11993           if(isColinear)
11994             {
11995               nbOfHit++;
11996               posEndElt++;
11997               ret=true;
11998             }
11999           delete eint;
12000           eCand->decrRef();
12001           if(!isColinear)
12002               break;
12003         }
12004       //push [posBaseElt,posEndElt) in newConnOfCell using e
12005       // 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!
12006       if(nbOfTurn==0)
12007         // at the begining of the connectivity (insert type)
12008         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
12009       else if((nbOfHit+nbOfTurn) != (nbs-1))
12010         // in the middle
12011         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
12012       if ((nbOfHit+nbOfTurn) == (nbs-1))
12013         // at the end (only quad points to deal with)
12014         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
12015       posBaseElt=posEndElt;
12016       e->decrRef();
12017     }
12018   if(!middles.empty())
12019     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
12020   return ret;
12021 }
12022
12023 /*!
12024  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
12025  *
12026  * \return  int - the number of new nodes created.
12027  * \sa MEDCouplingUMesh::split2DCells
12028  */
12029 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
12030 {
12031   checkConsistencyLight();
12032   int ncells(getNumberOfCells()),lgthToReach(getNodalConnectivityArrayLen()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
12033   MCAuto<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
12034   MCAuto<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
12035   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
12036   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
12037   const double *oldCoordsPtr(getCoords()->begin());
12038   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
12039   int prevPosOfCi(ciPtr[0]);
12040   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
12041     {
12042       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
12043       for(int j=0;j<sz;j++)
12044         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
12045       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
12046       for(int j=0;j<sz;j++)//loop over subedges of oldConn
12047         {
12048           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
12049           if(sz2==0)
12050             {
12051               if(j<sz-1)
12052                 cPtr[1]=oldConn[prevPosOfCi+2+j];
12053               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
12054               continue;
12055             }
12056           std::vector<INTERP_KERNEL::Node *> ns(3);
12057           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
12058           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
12059           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
12060           MCAuto<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
12061           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
12062             {
12063               cPtr[1]=subPtr[offset2+k];
12064               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
12065             }
12066           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
12067           if(j!=sz-1)
12068             { cPtr[1]=tmpEnd; }
12069           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
12070         }
12071       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
12072       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
12073     }
12074   if(c->end()!=cPtr)
12075     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
12076   _nodal_connec->decrRef();
12077   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
12078   addCoo->rearrange(2);
12079   MCAuto<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
12080   setCoords(coo);
12081   return addCoo->getNumberOfTuples();
12082 }
12083
12084 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
12085 {
12086   if(nodalConnec && nodalConnecIndex)
12087     {
12088       types.clear();
12089       const int *conn(nodalConnec->begin()),*connIndex(nodalConnecIndex->begin());
12090       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
12091       if(nbOfElem>0)
12092         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
12093           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
12094     }
12095 }
12096
12097 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
12098     _own_cell(true),_cell_id(-1),_nb_cell(0)
12099 {
12100   if(mesh)
12101     {
12102       mesh->incrRef();
12103       _nb_cell=mesh->getNumberOfCells();
12104     }
12105 }
12106
12107 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
12108 {
12109   if(_mesh)
12110     _mesh->decrRef();
12111   if(_own_cell)
12112     delete _cell;
12113 }
12114
12115 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
12116     _own_cell(false),_cell_id(bg-1),
12117     _nb_cell(end)
12118 {
12119   if(mesh)
12120     mesh->incrRef();
12121 }
12122
12123 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
12124 {
12125   _cell_id++;
12126   if(_cell_id<_nb_cell)
12127     {
12128       _cell->next();
12129       return _cell;
12130     }
12131   else
12132     return 0;
12133 }
12134
12135 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
12136 {
12137   if(_mesh)
12138     _mesh->incrRef();
12139 }
12140
12141 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
12142 {
12143   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
12144 }
12145
12146 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
12147 {
12148   if(_mesh)
12149     _mesh->decrRef();
12150 }
12151
12152 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
12153     _itc(itc),
12154     _bg(bg),_end(end)
12155 {
12156   if(_mesh)
12157     _mesh->incrRef();
12158 }
12159
12160 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
12161 {
12162   if(_mesh)
12163     _mesh->decrRef();
12164 }
12165
12166 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
12167 {
12168   return _type;
12169 }
12170
12171 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
12172 {
12173   return _end-_bg;
12174 }
12175
12176 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
12177 {
12178   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
12179 }
12180
12181 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
12182 {
12183   if(mesh)
12184     {
12185       mesh->incrRef();
12186       _nb_cell=mesh->getNumberOfCells();
12187     }
12188 }
12189
12190 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
12191 {
12192   if(_mesh)
12193     _mesh->decrRef();
12194   delete _cell;
12195 }
12196
12197 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
12198 {
12199   const int *c=_mesh->getNodalConnectivity()->begin();
12200   const int *ci=_mesh->getNodalConnectivityIndex()->begin();
12201   if(_cell_id<_nb_cell)
12202     {
12203       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
12204       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type)));
12205       int startId=_cell_id;
12206       _cell_id+=nbOfElems;
12207       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
12208     }
12209   else
12210     return 0;
12211 }
12212
12213 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
12214 {
12215   if(mesh)
12216     {
12217       _conn=mesh->getNodalConnectivity()->getPointer();
12218       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
12219     }
12220 }
12221
12222 void MEDCouplingUMeshCell::next()
12223 {
12224   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
12225     {
12226       _conn+=_conn_lgth;
12227       _conn_indx++;
12228     }
12229   _conn_lgth=_conn_indx[1]-_conn_indx[0];
12230 }
12231
12232 std::string MEDCouplingUMeshCell::repr() const
12233 {
12234   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
12235     {
12236       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
12237       oss << " : ";
12238       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
12239       return oss.str();
12240     }
12241   else
12242     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
12243 }
12244
12245 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
12246 {
12247   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
12248     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
12249   else
12250     return INTERP_KERNEL::NORM_ERROR;
12251 }
12252
12253 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
12254 {
12255   lgth=_conn_lgth;
12256   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
12257     return _conn;
12258   else
12259     return 0;
12260 }