Salome HOME
1) Fixed colinearize2D to handle degenerated cases (colinear SEG3 forming a circle).
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "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 ParaMEDMEM;
52
53 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
54
55 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 };
56
57 MEDCouplingUMesh *MEDCouplingUMesh::New()
58 {
59   return new MEDCouplingUMesh;
60 }
61
62 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
63 {
64   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
65   ret->setName(meshName);
66   ret->setMeshDimension(meshDim);
67   return ret;
68 }
69
70 /*!
71  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
72  * between \a this and the new mesh.
73  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
74  *          delete this mesh using decrRef() as it is no more needed. 
75  */
76 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
77 {
78   return clone(true);
79 }
80
81 /*!
82  * Returns a new MEDCouplingMesh which is a copy of \a this one.
83  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
84  * this mesh are shared by the new mesh.
85  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
86  *          delete this mesh using decrRef() as it is no more needed. 
87  */
88 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
89 {
90   return new MEDCouplingUMesh(*this,recDeepCpy);
91 }
92
93 /*!
94  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
95  * The coordinates are shared between \a this and the returned instance.
96  * 
97  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
98  * \sa MEDCouplingUMesh::deepCpy
99  */
100 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
101 {
102   checkConnectivityFullyDefined();
103   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
104   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
105   ret->setConnectivity(c,ci);
106   return ret.retn();
107 }
108
109 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
110 {
111   if(!other)
112     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
113   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
114   if(!otherC)
115     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
116   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
117   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
118 }
119
120 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
121 {
122   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
123   return ret;
124 }
125
126 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
127 {
128   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
129   ret.push_back(_nodal_connec);
130   ret.push_back(_nodal_connec_index);
131   return ret;
132 }
133
134 void MEDCouplingUMesh::updateTime() const
135 {
136   MEDCouplingPointSet::updateTime();
137   if(_nodal_connec)
138     {
139       updateTimeWith(*_nodal_connec);
140     }
141   if(_nodal_connec_index)
142     {
143       updateTimeWith(*_nodal_connec_index);
144     }
145 }
146
147 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
148 {
149 }
150
151 /*!
152  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
153  * then \a this mesh is most probably is writable, exchangeable and available for most
154  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
155  * this method to check that all is in order with \a this mesh.
156  *  \throw If the mesh dimension is not set.
157  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
158  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
159  *  \throw If the connectivity data array has more than one component.
160  *  \throw If the connectivity data array has a named component.
161  *  \throw If the connectivity index data array has more than one component.
162  *  \throw If the connectivity index data array has a named component.
163  */
164 void MEDCouplingUMesh::checkCoherency() const
165 {
166   if(_mesh_dim<-1)
167     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
168   if(_mesh_dim!=-1)
169     MEDCouplingPointSet::checkCoherency();
170   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
171     {
172       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
173         {
174           std::ostringstream message;
175           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
176           throw INTERP_KERNEL::Exception(message.str().c_str());
177         }
178     }
179   if(_nodal_connec)
180     {
181       if(_nodal_connec->getNumberOfComponents()!=1)
182         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
183       if(_nodal_connec->getInfoOnComponent(0)!="")
184         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
185     }
186   else
187     if(_mesh_dim!=-1)
188       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
189   if(_nodal_connec_index)
190     {
191       if(_nodal_connec_index->getNumberOfComponents()!=1)
192         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
193       if(_nodal_connec_index->getInfoOnComponent(0)!="")
194         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
195     }
196   else
197     if(_mesh_dim!=-1)
198       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
199 }
200
201 /*!
202  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
203  * then \a this mesh is most probably is writable, exchangeable and available for all
204  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
205  * method thoroughly checks the nodal connectivity.
206  *  \param [in] eps - a not used parameter.
207  *  \throw If the mesh dimension is not set.
208  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
209  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
210  *  \throw If the connectivity data array has more than one component.
211  *  \throw If the connectivity data array has a named component.
212  *  \throw If the connectivity index data array has more than one component.
213  *  \throw If the connectivity index data array has a named component.
214  *  \throw If number of nodes defining an element does not correspond to the type of element.
215  *  \throw If the nodal connectivity includes an invalid node id.
216  */
217 void MEDCouplingUMesh::checkCoherency1(double eps) const
218 {
219   checkCoherency();
220   if(_mesh_dim==-1)
221     return ;
222   int meshDim=getMeshDimension();
223   int nbOfNodes=getNumberOfNodes();
224   int nbOfCells=getNumberOfCells();
225   const int *ptr=_nodal_connec->getConstPointer();
226   const int *ptrI=_nodal_connec_index->getConstPointer();
227   for(int i=0;i<nbOfCells;i++)
228     {
229       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
230       if((int)cm.getDimension()!=meshDim)
231         {
232           std::ostringstream oss;
233           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
234           throw INTERP_KERNEL::Exception(oss.str().c_str());
235         }
236       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
237       if(!cm.isDynamic())
238         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
239           {
240             std::ostringstream oss;
241             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
242             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
243             throw INTERP_KERNEL::Exception(oss.str().c_str());
244           }
245       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
246         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
247           {
248             std::ostringstream oss;
249             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
250             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
251             throw INTERP_KERNEL::Exception(oss.str().c_str());
252           }
253       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
254         {
255           int nodeId=*w;
256           if(nodeId>=0)
257             {
258               if(nodeId>=nbOfNodes)
259                 {
260                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
261                   throw INTERP_KERNEL::Exception(oss.str().c_str());
262                 }
263             }
264           else if(nodeId<-1)
265             {
266               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
267               throw INTERP_KERNEL::Exception(oss.str().c_str());
268             }
269           else
270             {
271               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
272                 {
273                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
274                   throw INTERP_KERNEL::Exception(oss.str().c_str());
275                 }
276             }
277         }
278     }
279 }
280
281
282 /*!
283  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
284  * then \a this mesh is most probably is writable, exchangeable and available for all
285  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
286  *  \param [in] eps - a not used parameter.
287  *  \throw If the mesh dimension is not set.
288  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
289  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
290  *  \throw If the connectivity data array has more than one component.
291  *  \throw If the connectivity data array has a named component.
292  *  \throw If the connectivity index data array has more than one component.
293  *  \throw If the connectivity index data array has a named component.
294  *  \throw If number of nodes defining an element does not correspond to the type of element.
295  *  \throw If the nodal connectivity includes an invalid node id.
296  */
297 void MEDCouplingUMesh::checkCoherency2(double eps) const
298 {
299   checkCoherency1(eps);
300 }
301
302 /*!
303  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
304  * elements contained in the mesh. For more info on the mesh dimension see
305  * \ref MEDCouplingUMeshPage.
306  *  \param [in] meshDim - a new mesh dimension.
307  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
308  */
309 void MEDCouplingUMesh::setMeshDimension(int meshDim)
310 {
311   if(meshDim<-1 || meshDim>3)
312     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
313   _mesh_dim=meshDim;
314   declareAsNew();
315 }
316
317 /*!
318  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
319  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
320  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
321  *
322  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
323  *
324  *  \if ENABLE_EXAMPLES
325  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
326  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
327  *  \endif
328  */
329 void MEDCouplingUMesh::allocateCells(int nbOfCells)
330 {
331   if(nbOfCells<0)
332     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
333   if(_nodal_connec_index)
334     {
335       _nodal_connec_index->decrRef();
336     }
337   if(_nodal_connec)
338     {
339       _nodal_connec->decrRef();
340     }
341   _nodal_connec_index=DataArrayInt::New();
342   _nodal_connec_index->reserve(nbOfCells+1);
343   _nodal_connec_index->pushBackSilent(0);
344   _nodal_connec=DataArrayInt::New();
345   _nodal_connec->reserve(2*nbOfCells);
346   _types.clear();
347   declareAsNew();
348 }
349
350 /*!
351  * Appends a cell to the connectivity array. For deeper understanding what is
352  * happening see \ref MEDCouplingUMeshNodalConnectivity.
353  *  \param [in] type - type of cell to add.
354  *  \param [in] size - number of nodes constituting this cell.
355  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
356  * 
357  *  \if ENABLE_EXAMPLES
358  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
359  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
360  *  \endif
361  */
362 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
363 {
364   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
365   if(_nodal_connec_index==0)
366     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
367   if((int)cm.getDimension()==_mesh_dim)
368     {
369       if(!cm.isDynamic())
370         if(size!=(int)cm.getNumberOfNodes())
371           {
372             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
373             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
374             throw INTERP_KERNEL::Exception(oss.str().c_str());
375           }
376       int idx=_nodal_connec_index->back();
377       int val=idx+size+1;
378       _nodal_connec_index->pushBackSilent(val);
379       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
380       _types.insert(type);
381     }
382   else
383     {
384       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
385       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
386       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
387       throw INTERP_KERNEL::Exception(oss.str().c_str());
388     }
389 }
390
391 /*!
392  * Compacts data arrays to release unused memory. This method is to be called after
393  * finishing cell insertion using \a this->insertNextCell().
394  * 
395  *  \if ENABLE_EXAMPLES
396  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
397  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
398  *  \endif
399  */
400 void MEDCouplingUMesh::finishInsertingCells()
401 {
402   _nodal_connec->pack();
403   _nodal_connec_index->pack();
404   _nodal_connec->declareAsNew();
405   _nodal_connec_index->declareAsNew();
406   updateTime();
407 }
408
409 /*!
410  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
411  * Useful for python users.
412  */
413 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
414 {
415   return new MEDCouplingUMeshCellIterator(this);
416 }
417
418 /*!
419  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
420  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
421  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
422  * Useful for python users.
423  */
424 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
425 {
426   if(!checkConsecutiveCellTypes())
427     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
428   return new MEDCouplingUMeshCellByTypeEntry(this);
429 }
430
431 /*!
432  * Returns a set of all cell types available in \a this mesh.
433  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
434  * \warning this method does not throw any exception even if \a this is not defined.
435  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
436  */
437 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
438 {
439   return _types;
440 }
441
442 /*!
443  * This method returns the sorted list of geometric types in \a this.
444  * 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
445  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
446  *
447  * \throw if connectivity in \a this is not correctly defined.
448  *  
449  * \sa MEDCouplingMesh::getAllGeoTypes
450  */
451 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
452 {
453   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
454   checkConnectivityFullyDefined();
455   int nbOfCells(getNumberOfCells());
456   if(nbOfCells==0)
457     return ret;
458   if(getMeshLength()<1)
459     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
460   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
461   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
462   for(int i=1;i<nbOfCells;i++,ci++)
463     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
464       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
465   return ret;
466 }
467
468 /*!
469  * This method is a method that compares \a this and \a other.
470  * This method compares \b all attributes, even names and component names.
471  */
472 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
473 {
474   if(!other)
475     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
476   std::ostringstream oss; oss.precision(15);
477   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
478   if(!otherC)
479     {
480       reason="mesh given in input is not castable in MEDCouplingUMesh !";
481       return false;
482     }
483   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
484     return false;
485   if(_mesh_dim!=otherC->_mesh_dim)
486     {
487       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
488       reason=oss.str();
489       return false;
490     }
491   if(_types!=otherC->_types)
492     {
493       oss << "umesh geometric type mismatch :\nThis geometric types are :";
494       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
495         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
496       oss << "\nOther geometric types are :";
497       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
498         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
499       reason=oss.str();
500       return false;
501     }
502   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
503     if(_nodal_connec==0 || otherC->_nodal_connec==0)
504       {
505         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
506         return false;
507       }
508   if(_nodal_connec!=otherC->_nodal_connec)
509     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
510       {
511         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
512         return false;
513       }
514   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
515     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
516       {
517         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
518         return false;
519       }
520   if(_nodal_connec_index!=otherC->_nodal_connec_index)
521     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
522       {
523         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
524         return false;
525       }
526   return true;
527 }
528
529 /*!
530  * Checks if data arrays of this mesh (node coordinates, nodal
531  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
532  * not considered.
533  *  \param [in] other - the mesh to compare with.
534  *  \param [in] prec - precision value used to compare node coordinates.
535  *  \return bool - \a true if the two meshes are same.
536  */
537 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
538 {
539   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
540   if(!otherC)
541     return false;
542   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
543     return false;
544   if(_mesh_dim!=otherC->_mesh_dim)
545     return false;
546   if(_types!=otherC->_types)
547     return false;
548   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
549     if(_nodal_connec==0 || otherC->_nodal_connec==0)
550       return false;
551   if(_nodal_connec!=otherC->_nodal_connec)
552     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
553       return false;
554   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
555     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
556       return false;
557   if(_nodal_connec_index!=otherC->_nodal_connec_index)
558     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
559       return false;
560   return true;
561 }
562
563 /*!
564  * Checks if \a this and \a other meshes are geometrically equivalent with high
565  * probability, else an exception is thrown. The meshes are considered equivalent if
566  * (1) meshes contain the same number of nodes and the same number of elements of the
567  * same types (2) three cells of the two meshes (first, last and middle) are based
568  * on coincident nodes (with a specified precision).
569  *  \param [in] other - the mesh to compare with.
570  *  \param [in] prec - the precision used to compare nodes of the two meshes.
571  *  \throw If the two meshes do not match.
572  */
573 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
574 {
575   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
576   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
577   if(!otherC)
578     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
579 }
580
581 /*!
582  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
583  * cells each node belongs to.
584  * \warning For speed reasons, this method does not check if node ids in the nodal
585  *          connectivity correspond to the size of node coordinates array.
586  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
587  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
588  *        dividing cell ids in \a revNodal into groups each referring to one
589  *        node. Its every element (except the last one) is an index pointing to the
590  *         first id of a group of cells. For example cells sharing the node #1 are 
591  *        described by following range of indices: 
592  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
593  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
594  *        Number of cells sharing the *i*-th node is
595  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
596  * \throw If the coordinates array is not set.
597  * \throw If the nodal connectivity of cells is not defined.
598  * 
599  * \if ENABLE_EXAMPLES
600  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
601  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
602  * \endif
603  */
604 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
605 {
606   checkFullyDefined();
607   int nbOfNodes=getNumberOfNodes();
608   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
609   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
610   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
611   const int *conn=_nodal_connec->getConstPointer();
612   const int *connIndex=_nodal_connec_index->getConstPointer();
613   int nbOfCells=getNumberOfCells();
614   int nbOfEltsInRevNodal=0;
615   for(int eltId=0;eltId<nbOfCells;eltId++)
616     {
617       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
618       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
619       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
620         if(*iter>=0)//for polyhedrons
621           {
622             nbOfEltsInRevNodal++;
623             revNodalIndxPtr[(*iter)+1]++;
624           }
625     }
626   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
627   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
628   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
629   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
630   for(int eltId=0;eltId<nbOfCells;eltId++)
631     {
632       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
633       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
634       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
635         if(*iter>=0)//for polyhedrons
636           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
637     }
638 }
639
640 /// @cond INTERNAL
641
642 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
643 {
644   return id;
645 }
646
647 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
648 {
649   if(!compute)
650     return id+1;
651   else
652     {
653       if(cm.getOrientationStatus(nb,conn1,conn2))
654         return id+1;
655       else
656         return -(id+1);
657     }
658 }
659
660 class MinusOneSonsGenerator
661 {
662 public:
663   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
664   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
665   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
666   static const int DELTA=1;
667 private:
668   const INTERP_KERNEL::CellModel& _cm;
669 };
670
671 class MinusOneSonsGeneratorBiQuadratic
672 {
673 public:
674   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
675   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
676   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
677   static const int DELTA=1;
678 private:
679   const INTERP_KERNEL::CellModel& _cm;
680 };
681
682 class MinusTwoSonsGenerator
683 {
684 public:
685   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
686   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
687   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
688   static const int DELTA=2;
689 private:
690   const INTERP_KERNEL::CellModel& _cm;
691 };
692
693 /// @endcond
694
695 /*!
696  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
697  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
698  * describing correspondence between cells of \a this and the result meshes are
699  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
700  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
701  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
702  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
703  * \warning For speed reasons, this method does not check if node ids in the nodal
704  *          connectivity correspond to the size of node coordinates array.
705  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
706  *          to write this mesh to the MED file, its cells must be sorted using
707  *          sortCellsInMEDFileFrmt().
708  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
709  *         each cell of \a this mesh.
710  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
711  *        dividing cell ids in \a desc into groups each referring to one
712  *        cell of \a this mesh. Its every element (except the last one) is an index
713  *        pointing to the first id of a group of cells. For example cells of the
714  *        result mesh bounding the cell #1 of \a this mesh are described by following
715  *        range of indices:
716  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
717  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
718  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
719  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
720  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
721  *         by each cell of the result mesh.
722  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
723  *        in the result mesh,
724  *        dividing cell ids in \a revDesc into groups each referring to one
725  *        cell of the result mesh the same way as \a descIndx divides \a desc.
726  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
727  *        delete this mesh using decrRef() as it is no more needed.
728  *  \throw If the coordinates array is not set.
729  *  \throw If the nodal connectivity of cells is node defined.
730  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
731  *         revDescIndx == NULL.
732  * 
733  *  \if ENABLE_EXAMPLES
734  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
735  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
736  *  \endif
737  * \sa buildDescendingConnectivity2()
738  */
739 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
740 {
741   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
742 }
743
744 /*!
745  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
746  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
747  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
748  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
749  * \sa MEDCouplingUMesh::buildDescendingConnectivity
750  */
751 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
752 {
753   checkFullyDefined();
754   if(getMeshDimension()!=3)
755     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
756   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
757 }
758
759 /*!
760  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
761  * this->getMeshDimension(), that bound cells of \a this mesh. In
762  * addition arrays describing correspondence between cells of \a this and the result
763  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
764  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
765  *  mesh. This method differs from buildDescendingConnectivity() in that apart
766  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
767  * result meshes. So a positive id means that order of nodes in corresponding cells
768  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
769  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
770  * i.e. cell ids are one-based.
771  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
772  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
773  * \warning For speed reasons, this method does not check if node ids in the nodal
774  *          connectivity correspond to the size of node coordinates array.
775  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
776  *          to write this mesh to the MED file, its cells must be sorted using
777  *          sortCellsInMEDFileFrmt().
778  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
779  *         each cell of \a this mesh.
780  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
781  *        dividing cell ids in \a desc into groups each referring to one
782  *        cell of \a this mesh. Its every element (except the last one) is an index
783  *        pointing to the first id of a group of cells. For example cells of the
784  *        result mesh bounding the cell #1 of \a this mesh are described by following
785  *        range of indices:
786  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
787  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
788  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
789  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
790  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
791  *         by each cell of the result mesh.
792  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
793  *        in the result mesh,
794  *        dividing cell ids in \a revDesc into groups each referring to one
795  *        cell of the result mesh the same way as \a descIndx divides \a desc.
796  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
797  *        shares the node coordinates array with \a this mesh. The caller is to
798  *        delete this mesh using decrRef() as it is no more needed.
799  *  \throw If the coordinates array is not set.
800  *  \throw If the nodal connectivity of cells is node defined.
801  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
802  *         revDescIndx == NULL.
803  * 
804  *  \if ENABLE_EXAMPLES
805  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
806  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
807  *  \endif
808  * \sa buildDescendingConnectivity()
809  */
810 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
811 {
812   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
813 }
814
815 /*!
816  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
817  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
818  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
819  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
820  *
821  * \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
822  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
823  * \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.
824  */
825 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
826 {
827   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
828   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
829   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
831   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
832   meshDM1=0;
833   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
834 }
835
836 /*!
837  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
838  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
839  * excluding a set of meshdim-1 cells in input descending connectivity.
840  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
841  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
842  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
843  *
844  * \param [in] desc descending connectivity array.
845  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
846  * \param [in] revDesc reverse descending connectivity array.
847  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
848  * \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
849  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
850  * \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.
851  */
852 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
853                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
854 {
855   if(!desc || !descIndx || !revDesc || !revDescIndx)
856     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
857   const int *descPtr=desc->getConstPointer();
858   const int *descIPtr=descIndx->getConstPointer();
859   const int *revDescPtr=revDesc->getConstPointer();
860   const int *revDescIPtr=revDescIndx->getConstPointer();
861   //
862   int nbCells=descIndx->getNumberOfTuples()-1;
863   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
864   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
865   int *out1Ptr=out1->getPointer();
866   *out1Ptr++=0;
867   out0->reserve(desc->getNumberOfTuples());
868   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
869     {
870       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
871         {
872           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
873           s.erase(i);
874           out0->insertAtTheEnd(s.begin(),s.end());
875         }
876       *out1Ptr=out0->getNumberOfTuples();
877     }
878   neighbors=out0.retn();
879   neighborsIndx=out1.retn();
880 }
881
882 /*!
883  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
884  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
885  * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
886  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
887  *
888  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
889  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
890  * \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.
891  */
892 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
893 {
894   checkFullyDefined();
895   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
896   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
897   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
898   switch(mdim)
899   {
900     case 3:
901       {
902         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
903         break;
904       }
905     case 2:
906       {
907         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
908         break;
909       }
910     case 1:
911       {
912         mesh1D=const_cast<MEDCouplingUMesh *>(this);
913         mesh1D->incrRef();
914         break;
915       }
916     default:
917       {
918         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
919       }
920   }
921   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
922   mesh1D->getReverseNodalConnectivity(desc,descIndx);
923   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
924   ret0->alloc(desc->getNumberOfTuples(),1);
925   int *r0Pt(ret0->getPointer());
926   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
927   for(int i=0;i<nbNodes;i++,rni++)
928     {
929       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
930         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
931     }
932   neighbors=ret0.retn();
933   neighborsIdx=descIndx.retn();
934 }
935
936 /// @cond INTERNAL
937
938 /*!
939  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
940  * For speed reasons no check of this will be done.
941  */
942 template<class SonsGenerator>
943 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
944 {
945   if(!desc || !descIndx || !revDesc || !revDescIndx)
946     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
947   checkConnectivityFullyDefined();
948   int nbOfCells=getNumberOfCells();
949   int nbOfNodes=getNumberOfNodes();
950   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
951   int *revNodalIndxPtr=revNodalIndx->getPointer();
952   const int *conn=_nodal_connec->getConstPointer();
953   const int *connIndex=_nodal_connec_index->getConstPointer();
954   std::string name="Mesh constituent of "; name+=getName();
955   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
956   ret->setCoords(getCoords());
957   ret->allocateCells(2*nbOfCells);
958   descIndx->alloc(nbOfCells+1,1);
959   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
960   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
961   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
962     {
963       int pos=connIndex[eltId];
964       int posP1=connIndex[eltId+1];
965       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
966       SonsGenerator sg(cm);
967       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
968       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
969       for(unsigned i=0;i<nbOfSons;i++)
970         {
971           INTERP_KERNEL::NormalizedCellType cmsId;
972           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
973           for(unsigned k=0;k<nbOfNodesSon;k++)
974             if(tmp[k]>=0)
975               revNodalIndxPtr[tmp[k]+1]++;
976           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
977           revDesc2->pushBackSilent(eltId);
978         }
979       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
980     }
981   int nbOfCellsM1=ret->getNumberOfCells();
982   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
984   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
985   int *revNodalPtr=revNodal->getPointer();
986   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
987   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
988   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
989     {
990       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
991       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
992       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
993         if(*iter>=0)//for polyhedrons
994           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
995     }
996   //
997   DataArrayInt *commonCells=0,*commonCellsI=0;
998   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
999   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1000   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1001   int newNbOfCellsM1=-1;
1002   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
1003                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1004   std::vector<bool> isImpacted(nbOfCellsM1,false);
1005   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1006     for(int work2=work[0];work2!=work[1];work2++)
1007       isImpacted[commonCellsPtr[work2]]=true;
1008   const int *o2nM1Ptr=o2nM1->getConstPointer();
1009   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1010   const int *n2oM1Ptr=n2oM1->getConstPointer();
1011   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1012   ret2->copyTinyInfoFrom(this);
1013   desc->alloc(descIndx->back(),1);
1014   int *descPtr=desc->getPointer();
1015   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1016   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1017     {
1018       if(!isImpacted[i])
1019         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1020       else
1021         {
1022           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1023             {
1024               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1025               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1026             }
1027           else
1028             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1029         }
1030     }
1031   revDesc->reserve(newNbOfCellsM1);
1032   revDescIndx->alloc(newNbOfCellsM1+1,1);
1033   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1034   const int *revDesc2Ptr=revDesc2->getConstPointer();
1035   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1036     {
1037       int oldCellIdM1=n2oM1Ptr[i];
1038       if(!isImpacted[oldCellIdM1])
1039         {
1040           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1041           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1042         }
1043       else
1044         {
1045           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1046             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1047           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1048           commonCellsIPtr++;
1049         }
1050     }
1051   //
1052   return ret2.retn();
1053 }
1054
1055 struct MEDCouplingAccVisit
1056 {
1057   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1058   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1059   int _new_nb_of_nodes;
1060 };
1061
1062 /// @endcond
1063
1064 /*!
1065  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1066  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1067  * array of cell ids. Pay attention that after conversion all algorithms work slower
1068  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1069  * conversion due presence of invalid ids in the array of cells to convert, as a
1070  * result \a this mesh contains some already converted elements. In this case the 2D
1071  * mesh remains valid but 3D mesh becomes \b inconsistent!
1072  *  \warning This method can significantly modify the order of geometric types in \a this,
1073  *          hence, to write this mesh to the MED file, its cells must be sorted using
1074  *          sortCellsInMEDFileFrmt().
1075  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1076  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1077  *         cellIdsToConvertBg.
1078  *  \throw If the coordinates array is not set.
1079  *  \throw If the nodal connectivity of cells is node defined.
1080  *  \throw If dimension of \a this mesh is not either 2 or 3.
1081  *
1082  *  \if ENABLE_EXAMPLES
1083  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1084  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1085  *  \endif
1086  */
1087 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1088 {
1089   checkFullyDefined();
1090   int dim=getMeshDimension();
1091   if(dim<2 || dim>3)
1092     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1093   int nbOfCells(getNumberOfCells());
1094   if(dim==2)
1095     {
1096       const int *connIndex=_nodal_connec_index->getConstPointer();
1097       int *conn=_nodal_connec->getPointer();
1098       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1099         {
1100           if(*iter>=0 && *iter<nbOfCells)
1101             {
1102               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1103               if(!cm.isQuadratic())
1104                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1105               else
1106                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1107             }
1108           else
1109             {
1110               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1111               oss << " in range [0," << nbOfCells << ") !";
1112               throw INTERP_KERNEL::Exception(oss.str().c_str());
1113             }
1114         }
1115     }
1116   else
1117     {
1118       int *connIndex(_nodal_connec_index->getPointer());
1119       const int *connOld(_nodal_connec->getConstPointer());
1120       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1121       std::vector<bool> toBeDone(nbOfCells,false);
1122       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1123         {
1124           if(*iter>=0 && *iter<nbOfCells)
1125             toBeDone[*iter]=true;
1126           else
1127             {
1128               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1129               oss << " in range [0," << nbOfCells << ") !";
1130               throw INTERP_KERNEL::Exception(oss.str().c_str());
1131             }
1132         }
1133       for(int cellId=0;cellId<nbOfCells;cellId++)
1134         {
1135           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1136           int lgthOld(posP1-pos-1);
1137           if(toBeDone[cellId])
1138             {
1139               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1140               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1141               int *tmp(new int[nbOfFaces*lgthOld+1]);
1142               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1143               for(unsigned j=0;j<nbOfFaces;j++)
1144                 {
1145                   INTERP_KERNEL::NormalizedCellType type;
1146                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1147                   work+=offset;
1148                   *work++=-1;
1149                 }
1150               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1151               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1152               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1153               delete [] tmp;
1154             }
1155           else
1156             {
1157               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1158               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1159             }
1160         }
1161       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1162     }
1163   computeTypes();
1164 }
1165
1166 /*!
1167  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1168  * polyhedrons (if \a this is a 3D mesh).
1169  *  \warning As this method is purely for user-friendliness and no optimization is
1170  *          done to avoid construction of a useless vector, this method can be costly
1171  *          in memory.
1172  *  \throw If the coordinates array is not set.
1173  *  \throw If the nodal connectivity of cells is node defined.
1174  *  \throw If dimension of \a this mesh is not either 2 or 3.
1175  */
1176 void MEDCouplingUMesh::convertAllToPoly()
1177 {
1178   int nbOfCells=getNumberOfCells();
1179   std::vector<int> cellIds(nbOfCells);
1180   for(int i=0;i<nbOfCells;i++)
1181     cellIds[i]=i;
1182   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1183 }
1184
1185 /*!
1186  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1187  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1188  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1189  * base facet of the volume and the second half of nodes describes an opposite facet
1190  * having the same number of nodes as the base one. This method converts such
1191  * connectivity to a valid polyhedral format where connectivity of each facet is
1192  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1193  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1194  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1195  * a correct orientation of the first facet of a polyhedron, else orientation of a
1196  * corrected cell is reverse.<br>
1197  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1198  * it releases the user from boring description of polyhedra connectivity in the valid
1199  * format.
1200  *  \throw If \a this->getMeshDimension() != 3.
1201  *  \throw If \a this->getSpaceDimension() != 3.
1202  *  \throw If the nodal connectivity of cells is not defined.
1203  *  \throw If the coordinates array is not set.
1204  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1205  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1206  *
1207  *  \if ENABLE_EXAMPLES
1208  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1209  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1210  *  \endif
1211  */
1212 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1213 {
1214   checkFullyDefined();
1215   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1216     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1217   int nbOfCells=getNumberOfCells();
1218   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1219   newCi->alloc(nbOfCells+1,1);
1220   int *newci=newCi->getPointer();
1221   const int *ci=_nodal_connec_index->getConstPointer();
1222   const int *c=_nodal_connec->getConstPointer();
1223   newci[0]=0;
1224   for(int i=0;i<nbOfCells;i++)
1225     {
1226       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1227       if(type==INTERP_KERNEL::NORM_POLYHED)
1228         {
1229           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1230             {
1231               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1232               throw INTERP_KERNEL::Exception(oss.str().c_str());
1233             }
1234           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1235           if(n2%2!=0)
1236             {
1237               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 !";
1238               throw INTERP_KERNEL::Exception(oss.str().c_str());
1239             }
1240           int n1=(int)(n2/2);
1241           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)
1242         }
1243       else
1244         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1245     }
1246   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1247   newC->alloc(newci[nbOfCells],1);
1248   int *newc=newC->getPointer();
1249   for(int i=0;i<nbOfCells;i++)
1250     {
1251       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1252       if(type==INTERP_KERNEL::NORM_POLYHED)
1253         {
1254           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1255           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1256           *newc++=-1;
1257           for(std::size_t j=0;j<n1;j++)
1258             {
1259               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1260               newc[n1+5*j]=-1;
1261               newc[n1+5*j+1]=c[ci[i]+1+j];
1262               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1263               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1264               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1265             }
1266           newc+=n1*6;
1267         }
1268       else
1269         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1270     }
1271   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1272   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1273 }
1274
1275
1276 /*!
1277  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1278  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1279  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1280  *          to write this mesh to the MED file, its cells must be sorted using
1281  *          sortCellsInMEDFileFrmt().
1282  * \return \c true if at least one cell has been converted, \c false else. In the
1283  *         last case the nodal connectivity remains unchanged.
1284  * \throw If the coordinates array is not set.
1285  * \throw If the nodal connectivity of cells is not defined.
1286  * \throw If \a this->getMeshDimension() < 0.
1287  */
1288 bool MEDCouplingUMesh::unPolyze()
1289 {
1290   checkFullyDefined();
1291   int mdim=getMeshDimension();
1292   if(mdim<0)
1293     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1294   if(mdim<=1)
1295     return false;
1296   int nbOfCells=getNumberOfCells();
1297   if(nbOfCells<1)
1298     return false;
1299   int initMeshLgth=getMeshLength();
1300   int *conn=_nodal_connec->getPointer();
1301   int *index=_nodal_connec_index->getPointer();
1302   int posOfCurCell=0;
1303   int newPos=0;
1304   int lgthOfCurCell;
1305   bool ret=false;
1306   for(int i=0;i<nbOfCells;i++)
1307     {
1308       lgthOfCurCell=index[i+1]-posOfCurCell;
1309       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1310       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1311       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1312       int newLgth;
1313       if(cm.isDynamic())
1314         {
1315           switch(cm.getDimension())
1316           {
1317             case 2:
1318               {
1319                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1320                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1321                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1322                 break;
1323               }
1324             case 3:
1325               {
1326                 int nbOfFaces,lgthOfPolyhConn;
1327                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1328                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1329                 break;
1330               }
1331             case 1:
1332               {
1333                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1334                 break;
1335               }
1336           }
1337           ret=ret || (newType!=type);
1338           conn[newPos]=newType;
1339           newPos+=newLgth+1;
1340           posOfCurCell=index[i+1];
1341           index[i+1]=newPos;
1342         }
1343       else
1344         {
1345           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1346           newPos+=lgthOfCurCell;
1347           posOfCurCell+=lgthOfCurCell;
1348           index[i+1]=newPos;
1349         }
1350     }
1351   if(newPos!=initMeshLgth)
1352     _nodal_connec->reAlloc(newPos);
1353   if(ret)
1354     computeTypes();
1355   return ret;
1356 }
1357
1358 /*!
1359  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1360  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1361  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1362  *
1363  * \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 
1364  *             precision.
1365  */
1366 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1367 {
1368   checkFullyDefined();
1369   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1370     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1371   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1372   coords->recenterForMaxPrecision(eps);
1373   //
1374   int nbOfCells=getNumberOfCells();
1375   const int *conn=_nodal_connec->getConstPointer();
1376   const int *index=_nodal_connec_index->getConstPointer();
1377   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1378   connINew->alloc(nbOfCells+1,1);
1379   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1380   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1381   bool changed=false;
1382   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1383     {
1384       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1385         {
1386           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1387           changed=true;
1388         }
1389       else
1390         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1391       *connINewPtr=connNew->getNumberOfTuples();
1392     }
1393   if(changed)
1394     setConnectivity(connNew,connINew,false);
1395 }
1396
1397 /*!
1398  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1399  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1400  * the format of returned DataArrayInt instance.
1401  * 
1402  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1403  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1404  */
1405 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1406 {
1407   checkConnectivityFullyDefined();
1408   int nbOfCells=getNumberOfCells();
1409   const int *connIndex=_nodal_connec_index->getConstPointer();
1410   const int *conn=_nodal_connec->getConstPointer();
1411   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1412   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1413   std::vector<bool> retS(maxElt,false);
1414   for(int i=0;i<nbOfCells;i++)
1415     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1416       if(conn[j]>=0)
1417         retS[conn[j]]=true;
1418   int sz=0;
1419   for(int i=0;i<maxElt;i++)
1420     if(retS[i])
1421       sz++;
1422   DataArrayInt *ret=DataArrayInt::New();
1423   ret->alloc(sz,1);
1424   int *retPtr=ret->getPointer();
1425   for(int i=0;i<maxElt;i++)
1426     if(retS[i])
1427       *retPtr++=i;
1428   return ret;
1429 }
1430
1431 /*!
1432  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1433  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1434  */
1435 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1436 {
1437   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1438   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1439   for(int i=0;i<nbOfCells;i++)
1440     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1441       if(conn[j]>=0)
1442         {
1443           if(conn[j]<nbOfNodes)
1444             nodeIdsInUse[conn[j]]=true;
1445           else
1446             {
1447               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1448               throw INTERP_KERNEL::Exception(oss.str().c_str());
1449             }
1450         }
1451 }
1452
1453 /*!
1454  * Finds nodes not used in any cell and returns an array giving a new id to every node
1455  * by excluding the unused nodes, for which the array holds -1. The result array is
1456  * a mapping in "Old to New" mode. 
1457  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1458  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1459  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1460  *          if the node is unused or a new id else. The caller is to delete this
1461  *          array using decrRef() as it is no more needed.  
1462  *  \throw If the coordinates array is not set.
1463  *  \throw If the nodal connectivity of cells is not defined.
1464  *  \throw If the nodal connectivity includes an invalid id.
1465  *
1466  *  \if ENABLE_EXAMPLES
1467  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1468  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1469  *  \endif
1470  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1471  */
1472 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1473 {
1474   nbrOfNodesInUse=-1;
1475   int nbOfNodes(getNumberOfNodes());
1476   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1477   ret->alloc(nbOfNodes,1);
1478   int *traducer=ret->getPointer();
1479   std::fill(traducer,traducer+nbOfNodes,-1);
1480   int nbOfCells=getNumberOfCells();
1481   const int *connIndex=_nodal_connec_index->getConstPointer();
1482   const int *conn=_nodal_connec->getConstPointer();
1483   for(int i=0;i<nbOfCells;i++)
1484     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1485       if(conn[j]>=0)
1486         {
1487           if(conn[j]<nbOfNodes)
1488             traducer[conn[j]]=1;
1489           else
1490             {
1491               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1492               throw INTERP_KERNEL::Exception(oss.str().c_str());
1493             }
1494         }
1495   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1496   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1497   return ret.retn();
1498 }
1499
1500 /*!
1501  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1502  * For each cell in \b this the number of nodes constituting cell is computed.
1503  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1504  * So for pohyhedrons some nodes can be counted several times in the returned result.
1505  * 
1506  * \return a newly allocated array
1507  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1508  */
1509 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1510 {
1511   checkConnectivityFullyDefined();
1512   int nbOfCells=getNumberOfCells();
1513   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1514   ret->alloc(nbOfCells,1);
1515   int *retPtr=ret->getPointer();
1516   const int *conn=getNodalConnectivity()->getConstPointer();
1517   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1518   for(int i=0;i<nbOfCells;i++,retPtr++)
1519     {
1520       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1521         *retPtr=connI[i+1]-connI[i]-1;
1522       else
1523         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1524     }
1525   return ret.retn();
1526 }
1527
1528 /*!
1529  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1530  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1531  *
1532  * \return DataArrayInt * - new object to be deallocated by the caller.
1533  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1534  */
1535 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1536 {
1537   checkConnectivityFullyDefined();
1538   int nbOfCells=getNumberOfCells();
1539   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1540   ret->alloc(nbOfCells,1);
1541   int *retPtr=ret->getPointer();
1542   const int *conn=getNodalConnectivity()->getConstPointer();
1543   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1544   for(int i=0;i<nbOfCells;i++,retPtr++)
1545     {
1546       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1547       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1548         *retPtr=(int)s.size();
1549       else
1550         {
1551           s.erase(-1);
1552           *retPtr=(int)s.size();
1553         }
1554     }
1555   return ret.retn();
1556 }
1557
1558 /*!
1559  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1560  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1561  * 
1562  * \return a newly allocated array
1563  */
1564 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1565 {
1566   checkConnectivityFullyDefined();
1567   int nbOfCells=getNumberOfCells();
1568   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1569   ret->alloc(nbOfCells,1);
1570   int *retPtr=ret->getPointer();
1571   const int *conn=getNodalConnectivity()->getConstPointer();
1572   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1573   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1574     {
1575       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1576       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1577     }
1578   return ret.retn();
1579 }
1580
1581 /*!
1582  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1583  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1584  * array mean that the corresponding old node is no more used. 
1585  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1586  *           this->getNumberOfNodes() before call of this method. The caller is to
1587  *           delete this array using decrRef() as it is no more needed. 
1588  *  \throw If the coordinates array is not set.
1589  *  \throw If the nodal connectivity of cells is not defined.
1590  *  \throw If the nodal connectivity includes an invalid id.
1591  *  \sa areAllNodesFetched
1592  *
1593  *  \if ENABLE_EXAMPLES
1594  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1595  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1596  *  \endif
1597  */
1598 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1599 {
1600   return MEDCouplingPointSet::zipCoordsTraducer();
1601 }
1602
1603 /*!
1604  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1605  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1606  */
1607 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1608 {
1609   switch(compType)
1610   {
1611     case 0:
1612       return AreCellsEqual0(conn,connI,cell1,cell2);
1613     case 1:
1614       return AreCellsEqual1(conn,connI,cell1,cell2);
1615     case 2:
1616       return AreCellsEqual2(conn,connI,cell1,cell2);
1617     case 3:
1618       return AreCellsEqual3(conn,connI,cell1,cell2);
1619     case 7:
1620       return AreCellsEqual7(conn,connI,cell1,cell2);
1621   }
1622   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1623 }
1624
1625 /*!
1626  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1627  */
1628 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1629 {
1630   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1631     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1632   return 0;
1633 }
1634
1635 /*!
1636  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1637  */
1638 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1639 {
1640   int sz=connI[cell1+1]-connI[cell1];
1641   if(sz==connI[cell2+1]-connI[cell2])
1642     {
1643       if(conn[connI[cell1]]==conn[connI[cell2]])
1644         {
1645           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1646           unsigned dim=cm.getDimension();
1647           if(dim!=3)
1648             {
1649               if(dim!=1)
1650                 {
1651                   int sz1=2*(sz-1);
1652                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1653                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1654                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1655                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1656                   return work!=tmp+sz1?1:0;
1657                 }
1658               else
1659                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1660             }
1661           else
1662             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1663         }
1664     }
1665   return 0;
1666 }
1667
1668 /*!
1669  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1670  */
1671 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1672 {
1673   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1674     {
1675       if(conn[connI[cell1]]==conn[connI[cell2]])
1676         {
1677           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1678           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1679           return s1==s2?1:0;
1680         }
1681     }
1682   return 0;
1683 }
1684
1685 /*!
1686  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1687  */
1688 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1689 {
1690   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1691     {
1692       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1693       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1694       return s1==s2?1:0;
1695     }
1696   return 0;
1697 }
1698
1699 /*!
1700  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1701  */
1702 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1703 {
1704   int sz=connI[cell1+1]-connI[cell1];
1705   if(sz==connI[cell2+1]-connI[cell2])
1706     {
1707       if(conn[connI[cell1]]==conn[connI[cell2]])
1708         {
1709           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1710           unsigned dim=cm.getDimension();
1711           if(dim!=3)
1712             {
1713               if(dim!=1)
1714                 {
1715                   int sz1=2*(sz-1);
1716                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1717                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1718                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1719                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1720                   if(work!=tmp+sz1)
1721                     return 1;
1722                   else
1723                     {
1724                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1725                       std::reverse_iterator<int *> it2((int *)tmp);
1726                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1727                         return 2;
1728                       else
1729                         return 0;
1730                     }
1731
1732                   return work!=tmp+sz1?1:0;
1733                 }
1734               else
1735                 {//case of SEG2 and SEG3
1736                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1737                     return 1;
1738                   if(!cm.isQuadratic())
1739                     {
1740                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1741                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1742                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1743                         return 2;
1744                       return 0;
1745                     }
1746                   else
1747                     {
1748                       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])
1749                         return 2;
1750                       return 0;
1751                     }
1752                 }
1753             }
1754           else
1755             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1756         }
1757     }
1758   return 0;
1759 }
1760
1761 /*!
1762  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1763  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1764  * and result remains unchanged.
1765  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1766  * If in 'candidates' pool -1 value is considered as an empty value.
1767  * WARNING this method returns only ONE set of result !
1768  */
1769 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1770 {
1771   if(candidates.size()<1)
1772     return false;
1773   bool ret=false;
1774   std::vector<int>::const_iterator iter=candidates.begin();
1775   int start=(*iter++);
1776   for(;iter!=candidates.end();iter++)
1777     {
1778       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1779       if(status!=0)
1780         {
1781           if(!ret)
1782             {
1783               result->pushBackSilent(start);
1784               ret=true;
1785             }
1786           if(status==1)
1787             result->pushBackSilent(*iter);
1788           else
1789             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1790         }
1791     }
1792   return ret;
1793 }
1794
1795 /*!
1796  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1797  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1798  *
1799  * \param [in] compType input specifying the technique used to compare cells each other.
1800  *   - 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.
1801  *   - 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)
1802  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1803  *   - 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
1804  * can be used for users not sensitive to orientation of cell
1805  * \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.
1806  * \param [out] commonCells
1807  * \param [out] commonCellsI
1808  * \return the correspondance array old to new in a newly allocated array.
1809  * 
1810  */
1811 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1812 {
1813   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1814   getReverseNodalConnectivity(revNodal,revNodalI);
1815   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1816 }
1817
1818 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1819                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1820 {
1821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1822   int nbOfCells=nodalI->getNumberOfTuples()-1;
1823   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1824   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1825   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1826   std::vector<bool> isFetched(nbOfCells,false);
1827   if(startCellId==0)
1828     {
1829       for(int i=0;i<nbOfCells;i++)
1830         {
1831           if(!isFetched[i])
1832             {
1833               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1834               std::vector<int> v,v2;
1835               if(connOfNode!=connPtr+connIPtr[i+1])
1836                 {
1837                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1838                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1839                   connOfNode++;
1840                 }
1841               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1842                 if(*connOfNode>=0)
1843                   {
1844                     v=v2;
1845                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1846                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1847                     v2.resize(std::distance(v2.begin(),it));
1848                   }
1849               if(v2.size()>1)
1850                 {
1851                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1852                     {
1853                       int pos=commonCellsI->back();
1854                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1855                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1856                         isFetched[*it]=true;
1857                     }
1858                 }
1859             }
1860         }
1861     }
1862   else
1863     {
1864       for(int i=startCellId;i<nbOfCells;i++)
1865         {
1866           if(!isFetched[i])
1867             {
1868               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1869               std::vector<int> v,v2;
1870               if(connOfNode!=connPtr+connIPtr[i+1])
1871                 {
1872                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1873                   connOfNode++;
1874                 }
1875               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1876                 if(*connOfNode>=0)
1877                   {
1878                     v=v2;
1879                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1880                     v2.resize(std::distance(v2.begin(),it));
1881                   }
1882               if(v2.size()>1)
1883                 {
1884                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1885                     {
1886                       int pos=commonCellsI->back();
1887                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1888                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1889                         isFetched[*it]=true;
1890                     }
1891                 }
1892             }
1893         }
1894     }
1895   commonCellsArr=commonCells.retn();
1896   commonCellsIArr=commonCellsI.retn();
1897 }
1898
1899 /*!
1900  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1901  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1902  * than \a other->getNumberOfCells() in the returned array means that there is no
1903  * corresponding cell in \a this mesh.
1904  * It is expected that \a this and \a other meshes share the same node coordinates
1905  * array, if it is not so an exception is thrown. 
1906  *  \param [in] other - the mesh to compare with.
1907  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1908  *         valid values [0,1,2], see zipConnectivityTraducer().
1909  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1910  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1911  *         values. The caller is to delete this array using
1912  *         decrRef() as it is no more needed.
1913  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1914  *         mesh.
1915  *
1916  *  \if ENABLE_EXAMPLES
1917  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1918  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1919  *  \endif
1920  *  \sa checkDeepEquivalOnSameNodesWith()
1921  *  \sa checkGeoEquivalWith()
1922  */
1923 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1924 {
1925   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1926   int nbOfCells=getNumberOfCells();
1927   static const int possibleCompType[]={0,1,2};
1928   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1929     {
1930       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1931       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1932       oss << " !";
1933       throw INTERP_KERNEL::Exception(oss.str().c_str());
1934     }
1935   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1936   arr=o2n->substr(nbOfCells);
1937   arr->setName(other->getName());
1938   int tmp;
1939   if(other->getNumberOfCells()==0)
1940     return true;
1941   return arr->getMaxValue(tmp)<nbOfCells;
1942 }
1943
1944 /*!
1945  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1946  * This method tries to determine if \b other is fully included in \b this.
1947  * The main difference is that this method is not expected to throw exception.
1948  * This method has two outputs :
1949  *
1950  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1951  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1952  */
1953 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1954 {
1955   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1956   DataArrayInt *commonCells=0,*commonCellsI=0;
1957   int thisNbCells=getNumberOfCells();
1958   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1959   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1960   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1961   int otherNbCells=other->getNumberOfCells();
1962   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1963   arr2->alloc(otherNbCells,1);
1964   arr2->fillWithZero();
1965   int *arr2Ptr=arr2->getPointer();
1966   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1967   for(int i=0;i<nbOfCommon;i++)
1968     {
1969       int start=commonCellsPtr[commonCellsIPtr[i]];
1970       if(start<thisNbCells)
1971         {
1972           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1973             {
1974               int sig=commonCellsPtr[j]>0?1:-1;
1975               int val=std::abs(commonCellsPtr[j])-1;
1976               if(val>=thisNbCells)
1977                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1978             }
1979         }
1980     }
1981   arr2->setName(other->getName());
1982   if(arr2->presenceOfValue(0))
1983     return false;
1984   arr=arr2.retn();
1985   return true;
1986 }
1987
1988 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1989 {
1990   if(!other)
1991     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1992   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1993   if(!otherC)
1994     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1995   std::vector<const MEDCouplingUMesh *> ms(2);
1996   ms[0]=this;
1997   ms[1]=otherC;
1998   return MergeUMeshesOnSameCoords(ms);
1999 }
2000
2001 /*!
2002  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2003  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2004  * cellIds is not given explicitely but by a range python like.
2005  * 
2006  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
2007  * \return a newly allocated
2008  * 
2009  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2010  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2011  */
2012 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2013 {
2014   if(getMeshDimension()!=-1)
2015     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2016   else
2017     {
2018       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2019       if(newNbOfCells!=1)
2020         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2021       if(start!=0)
2022         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2023       incrRef();
2024       return const_cast<MEDCouplingUMesh *>(this);
2025     }
2026 }
2027
2028 /*!
2029  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2030  * The result mesh shares or not the node coordinates array with \a this mesh depending
2031  * on \a keepCoords parameter.
2032  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2033  *           to write this mesh to the MED file, its cells must be sorted using
2034  *           sortCellsInMEDFileFrmt().
2035  *  \param [in] begin - an array of cell ids to include to the new mesh.
2036  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2037  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2038  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2039  *         by calling zipCoords().
2040  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2041  *         to delete this mesh using decrRef() as it is no more needed. 
2042  *  \throw If the coordinates array is not set.
2043  *  \throw If the nodal connectivity of cells is not defined.
2044  *  \throw If any cell id in the array \a begin is not valid.
2045  *
2046  *  \if ENABLE_EXAMPLES
2047  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2048  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2049  *  \endif
2050  */
2051 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2052 {
2053   if(getMeshDimension()!=-1)
2054     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2055   else
2056     {
2057       if(end-begin!=1)
2058         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2059       if(begin[0]!=0)
2060         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2061       incrRef();
2062       return const_cast<MEDCouplingUMesh *>(this);
2063     }
2064 }
2065
2066 /*!
2067  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2068  *
2069  * 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.
2070  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2071  * The number of cells of \b this will remain the same with this method.
2072  *
2073  * \param [in] begin begin of cell ids (included) of cells in this to assign
2074  * \param [in] end end of cell ids (excluded) of cells in this to assign
2075  * \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 ).
2076  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2077  */
2078 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2079 {
2080   checkConnectivityFullyDefined();
2081   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2082   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2083     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2084   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2085     {
2086       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2087       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2088       throw INTERP_KERNEL::Exception(oss.str().c_str());
2089     }
2090   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2091   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2092     {
2093       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2094       throw INTERP_KERNEL::Exception(oss.str().c_str());
2095     }
2096   int nbOfCells=getNumberOfCells();
2097   bool easyAssign=true;
2098   const int *connI=_nodal_connec_index->getConstPointer();
2099   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2100   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2101     {
2102       if(*it>=0 && *it<nbOfCells)
2103         {
2104           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2105         }
2106       else
2107         {
2108           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2109           throw INTERP_KERNEL::Exception(oss.str().c_str());
2110         }
2111     }
2112   if(easyAssign)
2113     {
2114       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2115       computeTypes();
2116     }
2117   else
2118     {
2119       DataArrayInt *arrOut=0,*arrIOut=0;
2120       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2121                                                arrOut,arrIOut);
2122       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2123       setConnectivity(arrOut,arrIOut,true);
2124     }
2125 }
2126
2127 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2128 {
2129   checkConnectivityFullyDefined();
2130   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2131   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2132     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2133   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2134     {
2135       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2136       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2137       throw INTERP_KERNEL::Exception(oss.str().c_str());
2138     }
2139   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2140   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2141     {
2142       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2143       throw INTERP_KERNEL::Exception(oss.str().c_str());
2144     }
2145   int nbOfCells=getNumberOfCells();
2146   bool easyAssign=true;
2147   const int *connI=_nodal_connec_index->getConstPointer();
2148   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2149   int it=start;
2150   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2151     {
2152       if(it>=0 && it<nbOfCells)
2153         {
2154           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2155         }
2156       else
2157         {
2158           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2159           throw INTERP_KERNEL::Exception(oss.str().c_str());
2160         }
2161     }
2162   if(easyAssign)
2163     {
2164       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2165       computeTypes();
2166     }
2167   else
2168     {
2169       DataArrayInt *arrOut=0,*arrIOut=0;
2170       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2171                                                 arrOut,arrIOut);
2172       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2173       setConnectivity(arrOut,arrIOut,true);
2174     }
2175 }                      
2176
2177 /*!
2178  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2179  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2180  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2181  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2182  *
2183  * \param [in] begin input start of array of node ids.
2184  * \param [in] end input end of array of node ids.
2185  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2186  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2187  */
2188 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2189 {
2190   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2191   checkConnectivityFullyDefined();
2192   int tmp=-1;
2193   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2194   std::vector<bool> fastFinder(sz,false);
2195   for(const int *work=begin;work!=end;work++)
2196     if(*work>=0 && *work<sz)
2197       fastFinder[*work]=true;
2198   int nbOfCells=getNumberOfCells();
2199   const int *conn=getNodalConnectivity()->getConstPointer();
2200   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2201   for(int i=0;i<nbOfCells;i++)
2202     {
2203       int ref=0,nbOfHit=0;
2204       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2205         if(*work2>=0)
2206           {
2207             ref++;
2208             if(fastFinder[*work2])
2209               nbOfHit++;
2210           }
2211       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2212         cellIdsKept->pushBackSilent(i);
2213     }
2214   cellIdsKeptArr=cellIdsKept.retn();
2215 }
2216
2217 /*!
2218  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2219  * this->getMeshDimension(), that bound some cells of \a this mesh.
2220  * The cells of lower dimension to include to the result mesh are selected basing on
2221  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2222  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2223  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2224  * created mesh shares the node coordinates array with \a this mesh. 
2225  *  \param [in] begin - the array of node ids.
2226  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2227  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2228  *         array \a begin are added, else cells whose any node is in the
2229  *         array \a begin are added.
2230  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2231  *         to delete this mesh using decrRef() as it is no more needed. 
2232  *  \throw If the coordinates array is not set.
2233  *  \throw If the nodal connectivity of cells is not defined.
2234  *  \throw If any node id in \a begin is not valid.
2235  *
2236  *  \if ENABLE_EXAMPLES
2237  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2238  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2239  *  \endif
2240  */
2241 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2242 {
2243   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2244   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2245   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2246   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2247   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2248 }
2249
2250 /*!
2251  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2252  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2253  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2254  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2255  *         by calling zipCoords().
2256  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2257  *         to delete this mesh using decrRef() as it is no more needed. 
2258  *  \throw If the coordinates array is not set.
2259  *  \throw If the nodal connectivity of cells is not defined.
2260  *
2261  *  \if ENABLE_EXAMPLES
2262  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2263  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2264  *  \endif
2265  */
2266 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2267 {
2268   DataArrayInt *desc=DataArrayInt::New();
2269   DataArrayInt *descIndx=DataArrayInt::New();
2270   DataArrayInt *revDesc=DataArrayInt::New();
2271   DataArrayInt *revDescIndx=DataArrayInt::New();
2272   //
2273   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2274   revDesc->decrRef();
2275   desc->decrRef();
2276   descIndx->decrRef();
2277   int nbOfCells=meshDM1->getNumberOfCells();
2278   const int *revDescIndxC=revDescIndx->getConstPointer();
2279   std::vector<int> boundaryCells;
2280   for(int i=0;i<nbOfCells;i++)
2281     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2282       boundaryCells.push_back(i);
2283   revDescIndx->decrRef();
2284   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2285   return ret;
2286 }
2287
2288 /*!
2289  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2290  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2291  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2292  */
2293 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2294 {
2295   checkFullyDefined();
2296   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2297   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2298   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2299   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2300   //
2301   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2302   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2303   //
2304   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2305   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2306   const int *revDescPtr=revDesc->getConstPointer();
2307   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2308   int nbOfCells=getNumberOfCells();
2309   std::vector<bool> ret1(nbOfCells,false);
2310   int sz=0;
2311   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2312     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2313       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2314   //
2315   DataArrayInt *ret2=DataArrayInt::New();
2316   ret2->alloc(sz,1);
2317   int *ret2Ptr=ret2->getPointer();
2318   sz=0;
2319   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2320     if(*it)
2321       *ret2Ptr++=sz;
2322   ret2->setName("BoundaryCells");
2323   return ret2;
2324 }
2325
2326 /*!
2327  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2328  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2329  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2330  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2331  *
2332  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2333  * This method method returns cells ids set s = s1 + s2 where :
2334  * 
2335  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2336  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2337  *
2338  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2339  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2340  *
2341  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2342  * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2343  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2344  */
2345 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2346 {
2347   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2348     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2349   checkConnectivityFullyDefined();
2350   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2351   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2352     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2353   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2354   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2355   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2356   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2357   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2358   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2359   DataArrayInt *idsOtherInConsti=0;
2360   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2361   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2362   if(!b)
2363     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2364   std::set<int> s1;
2365   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2366     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2367   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2369   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2370   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2371   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2372   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2373   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2374   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2375   neighThisPartAuto=0;
2376   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2377   const int li[2]={0,1};
2378   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2379   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2380   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2381   s_renum1->sort();
2382   //
2383   cellIdsRk0=s0arr.retn();
2384   cellIdsRk1=s_renum1.retn();
2385 }
2386
2387 /*!
2388  * 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
2389  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2390  * 
2391  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2392  */
2393 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2394 {
2395   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2397   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2398   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2399   //
2400   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2401   revDesc=0; desc=0; descIndx=0;
2402   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2403   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2404   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2405 }
2406
2407 /*!
2408  * Finds nodes lying on the boundary of \a this mesh.
2409  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2410  *          nodes. The caller is to delete this array using decrRef() as it is no
2411  *          more needed.
2412  *  \throw If the coordinates array is not set.
2413  *  \throw If the nodal connectivity of cells is node defined.
2414  *
2415  *  \if ENABLE_EXAMPLES
2416  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2417  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2418  *  \endif
2419  */
2420 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2421 {
2422   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2423   return skin->computeFetchedNodeIds();
2424 }
2425
2426 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2427 {
2428   incrRef();
2429   return const_cast<MEDCouplingUMesh *>(this);
2430 }
2431
2432 /*!
2433  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2434  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2435  * 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.
2436  * 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.
2437  * 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.
2438  *
2439  * \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
2440  *             parameter is altered during the call.
2441  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2442  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2443  * \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.
2444  *
2445  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2446  */
2447 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2448                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2449 {
2450   checkFullyDefined();
2451   otherDimM1OnSameCoords.checkFullyDefined();
2452   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2453     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2454   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2455     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2456   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2457   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2458   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2460   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2461   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2462   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2463   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2464   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2465   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2466   //
2467   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2468   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2469   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2470   DataArrayInt *idsTmp=0;
2471   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2472   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2473   if(!b)
2474     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2475   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2476   DataArrayInt *tmp0=0,*tmp1=0;
2477   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2478   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2479   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2480   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2481   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2482   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2483   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2484   //
2485   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2486   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2487   nodeIdsToDuplicate=s3.retn();
2488 }
2489
2490 /*!
2491  * This method operates a modification of the connectivity and coords in \b this.
2492  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2493  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2494  * 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
2495  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2496  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2497  * 
2498  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2499  * 
2500  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2501  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2502  */
2503 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2504 {
2505   int nbOfNodes=getNumberOfNodes();
2506   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2507   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2508 }
2509
2510 /*!
2511  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2512  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2513  *
2514  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2515  *
2516  * \sa renumberNodesInConn
2517  */
2518 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2519 {
2520   checkConnectivityFullyDefined();
2521   int *conn(getNodalConnectivity()->getPointer());
2522   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2523   int nbOfCells(getNumberOfCells());
2524   for(int i=0;i<nbOfCells;i++)
2525     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2526       {
2527         int& node=conn[iconn];
2528         if(node>=0)//avoid polyhedron separator
2529           {
2530             node+=offset;
2531           }
2532       }
2533   _nodal_connec->declareAsNew();
2534   updateTime();
2535 }
2536
2537 /*!
2538  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2539  *  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
2540  *  of a big mesh.
2541  */
2542 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2543 {
2544   checkConnectivityFullyDefined();
2545   int *conn(getNodalConnectivity()->getPointer());
2546   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2547   int nbOfCells(getNumberOfCells());
2548   for(int i=0;i<nbOfCells;i++)
2549     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2550       {
2551         int& node=conn[iconn];
2552         if(node>=0)//avoid polyhedron separator
2553           {
2554             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2555             if(it!=newNodeNumbersO2N.end())
2556               {
2557                 node=(*it).second;
2558               }
2559             else
2560               {
2561                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2562                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2563               }
2564           }
2565       }
2566   _nodal_connec->declareAsNew();
2567   updateTime();
2568 }
2569
2570 /*!
2571  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2572  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2573  * This method is a generalization of shiftNodeNumbersInConn().
2574  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2575  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2576  *         this->getNumberOfNodes(), in "Old to New" mode. 
2577  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2578  *  \throw If the nodal connectivity of cells is not defined.
2579  *
2580  *  \if ENABLE_EXAMPLES
2581  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2582  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2583  *  \endif
2584  */
2585 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2586 {
2587   checkConnectivityFullyDefined();
2588   int *conn=getNodalConnectivity()->getPointer();
2589   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2590   int nbOfCells(getNumberOfCells());
2591   for(int i=0;i<nbOfCells;i++)
2592     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2593       {
2594         int& node=conn[iconn];
2595         if(node>=0)//avoid polyhedron separator
2596           {
2597             node=newNodeNumbersO2N[node];
2598           }
2599       }
2600   _nodal_connec->declareAsNew();
2601   updateTime();
2602 }
2603
2604 /*!
2605  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2606  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2607  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2608  * 
2609  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2610  */
2611 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2612 {
2613   checkConnectivityFullyDefined();
2614   int *conn=getNodalConnectivity()->getPointer();
2615   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2616   int nbOfCells=getNumberOfCells();
2617   for(int i=0;i<nbOfCells;i++)
2618     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2619       {
2620         int& node=conn[iconn];
2621         if(node>=0)//avoid polyhedron separator
2622           {
2623             node+=delta;
2624           }
2625       }
2626   _nodal_connec->declareAsNew();
2627   updateTime();
2628 }
2629
2630 /*!
2631  * This method operates a modification of the connectivity in \b this.
2632  * 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.
2633  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2634  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2635  * 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
2636  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2637  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2638  * 
2639  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2640  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2641  * 
2642  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2643  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2644  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2645  */
2646 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2647 {
2648   checkConnectivityFullyDefined();
2649   std::map<int,int> m;
2650   int val=offset;
2651   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2652     m[*work]=val;
2653   int *conn=getNodalConnectivity()->getPointer();
2654   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2655   int nbOfCells=getNumberOfCells();
2656   for(int i=0;i<nbOfCells;i++)
2657     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2658       {
2659         int& node=conn[iconn];
2660         if(node>=0)//avoid polyhedron separator
2661           {
2662             std::map<int,int>::iterator it=m.find(node);
2663             if(it!=m.end())
2664               node=(*it).second;
2665           }
2666       }
2667   updateTime();
2668 }
2669
2670 /*!
2671  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2672  *
2673  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2674  * After the call of this method the number of cells remains the same as before.
2675  *
2676  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2677  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2678  * be strictly in [0;this->getNumberOfCells()).
2679  *
2680  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2681  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2682  * should be contained in[0;this->getNumberOfCells()).
2683  * 
2684  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2685  */
2686 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2687 {
2688   checkConnectivityFullyDefined();
2689   int nbCells=getNumberOfCells();
2690   const int *array=old2NewBg;
2691   if(check)
2692     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2693   //
2694   const int *conn=_nodal_connec->getConstPointer();
2695   const int *connI=_nodal_connec_index->getConstPointer();
2696   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2697   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2698   const int *n2oPtr=n2o->begin();
2699   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2700   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2701   newConn->copyStringInfoFrom(*_nodal_connec);
2702   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2703   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2704   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2705   //
2706   int *newC=newConn->getPointer();
2707   int *newCI=newConnI->getPointer();
2708   int loc=0;
2709   newCI[0]=loc;
2710   for(int i=0;i<nbCells;i++)
2711     {
2712       int pos=n2oPtr[i];
2713       int nbOfElts=connI[pos+1]-connI[pos];
2714       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2715       loc+=nbOfElts;
2716       newCI[i+1]=loc;
2717     }
2718   //
2719   setConnectivity(newConn,newConnI);
2720   if(check)
2721     free(const_cast<int *>(array));
2722 }
2723
2724 /*!
2725  * Finds cells whose bounding boxes intersect a given bounding box.
2726  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2727  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2728  *         zMax (if in 3D). 
2729  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2730  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2731  *         extent of the bounding box of cell to produce an addition to this bounding box.
2732  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2733  *         cells. The caller is to delete this array using decrRef() as it is no more
2734  *         needed. 
2735  *  \throw If the coordinates array is not set.
2736  *  \throw If the nodal connectivity of cells is not defined.
2737  *
2738  *  \if ENABLE_EXAMPLES
2739  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2740  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2741  *  \endif
2742  */
2743 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2744 {
2745   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2746   if(getMeshDimension()==-1)
2747     {
2748       elems->pushBackSilent(0);
2749       return elems.retn();
2750     }
2751   int dim=getSpaceDimension();
2752   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2753   const int* conn      = getNodalConnectivity()->getConstPointer();
2754   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2755   const double* coords = getCoords()->getConstPointer();
2756   int nbOfCells=getNumberOfCells();
2757   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2758     {
2759       for (int i=0; i<dim; i++)
2760         {
2761           elem_bb[i*2]=std::numeric_limits<double>::max();
2762           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2763         }
2764
2765       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2766         {
2767           int node= conn[inode];
2768           if(node>=0)//avoid polyhedron separator
2769             {
2770               for (int idim=0; idim<dim; idim++)
2771                 {
2772                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2773                     {
2774                       elem_bb[idim*2] = coords[node*dim+idim] ;
2775                     }
2776                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2777                     {
2778                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2779                     }
2780                 }
2781             }
2782         }
2783       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2784         elems->pushBackSilent(ielem);
2785     }
2786   return elems.retn();
2787 }
2788
2789 /*!
2790  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2791  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2792  * added in 'elems' parameter.
2793  */
2794 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2795 {
2796   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2797   if(getMeshDimension()==-1)
2798     {
2799       elems->pushBackSilent(0);
2800       return elems.retn();
2801     }
2802   int dim=getSpaceDimension();
2803   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2804   const int* conn      = getNodalConnectivity()->getConstPointer();
2805   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2806   const double* coords = getCoords()->getConstPointer();
2807   int nbOfCells=getNumberOfCells();
2808   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2809     {
2810       for (int i=0; i<dim; i++)
2811         {
2812           elem_bb[i*2]=std::numeric_limits<double>::max();
2813           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2814         }
2815
2816       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2817         {
2818           int node= conn[inode];
2819           if(node>=0)//avoid polyhedron separator
2820             {
2821               for (int idim=0; idim<dim; idim++)
2822                 {
2823                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2824                     {
2825                       elem_bb[idim*2] = coords[node*dim+idim] ;
2826                     }
2827                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2828                     {
2829                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2830                     }
2831                 }
2832             }
2833         }
2834       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2835         elems->pushBackSilent(ielem);
2836     }
2837   return elems.retn();
2838 }
2839
2840 /*!
2841  * Returns a type of a cell by its id.
2842  *  \param [in] cellId - the id of the cell of interest.
2843  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2844  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2845  */
2846 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2847 {
2848   const int *ptI=_nodal_connec_index->getConstPointer();
2849   const int *pt=_nodal_connec->getConstPointer();
2850   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2851     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2852   else
2853     {
2854       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2855       throw INTERP_KERNEL::Exception(oss.str().c_str());
2856     }
2857 }
2858
2859 /*!
2860  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2861  * This method does not throw exception if geometric type \a type is not in \a this.
2862  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2863  * The coordinates array is not considered here.
2864  *
2865  * \param [in] type the geometric type
2866  * \return cell ids in this having geometric type \a type.
2867  */
2868 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2869 {
2870
2871   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2872   ret->alloc(0,1);
2873   checkConnectivityFullyDefined();
2874   int nbCells=getNumberOfCells();
2875   int mdim=getMeshDimension();
2876   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2877   if(mdim!=(int)cm.getDimension())
2878     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2879   const int *ptI=_nodal_connec_index->getConstPointer();
2880   const int *pt=_nodal_connec->getConstPointer();
2881   for(int i=0;i<nbCells;i++)
2882     {
2883       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2884         ret->pushBackSilent(i);
2885     }
2886   return ret.retn();
2887 }
2888
2889 /*!
2890  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2891  */
2892 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2893 {
2894   const int *ptI=_nodal_connec_index->getConstPointer();
2895   const int *pt=_nodal_connec->getConstPointer();
2896   int nbOfCells=getNumberOfCells();
2897   int ret=0;
2898   for(int i=0;i<nbOfCells;i++)
2899     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2900       ret++;
2901   return ret;
2902 }
2903
2904 /*!
2905  * Returns the nodal connectivity of a given cell.
2906  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2907  * all returned node ids can be used in getCoordinatesOfNode().
2908  *  \param [in] cellId - an id of the cell of interest.
2909  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2910  *         cleared before the appending.
2911  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2912  */
2913 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2914 {
2915   const int *ptI=_nodal_connec_index->getConstPointer();
2916   const int *pt=_nodal_connec->getConstPointer();
2917   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2918     if(*w>=0)
2919       conn.push_back(*w);
2920 }
2921
2922 std::string MEDCouplingUMesh::simpleRepr() const
2923 {
2924   static const char msg0[]="No coordinates specified !";
2925   std::ostringstream ret;
2926   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2927   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2928   int tmpp1,tmpp2;
2929   double tt=getTime(tmpp1,tmpp2);
2930   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2931   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2932   if(_mesh_dim>=-1)
2933     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2934   else
2935     { ret << " Mesh dimension has not been set or is invalid !"; }
2936   if(_coords!=0)
2937     {
2938       const int spaceDim=getSpaceDimension();
2939       ret << spaceDim << "\nInfo attached on space dimension : ";
2940       for(int i=0;i<spaceDim;i++)
2941         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2942       ret << "\n";
2943     }
2944   else
2945     ret << msg0 << "\n";
2946   ret << "Number of nodes : ";
2947   if(_coords!=0)
2948     ret << getNumberOfNodes() << "\n";
2949   else
2950     ret << msg0 << "\n";
2951   ret << "Number of cells : ";
2952   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2953     ret << getNumberOfCells() << "\n";
2954   else
2955     ret << "No connectivity specified !" << "\n";
2956   ret << "Cell types present : ";
2957   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2958     {
2959       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2960       ret << cm.getRepr() << " ";
2961     }
2962   ret << "\n";
2963   return ret.str();
2964 }
2965
2966 std::string MEDCouplingUMesh::advancedRepr() const
2967 {
2968   std::ostringstream ret;
2969   ret << simpleRepr();
2970   ret << "\nCoordinates array : \n___________________\n\n";
2971   if(_coords)
2972     _coords->reprWithoutNameStream(ret);
2973   else
2974     ret << "No array set !\n";
2975   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2976   reprConnectivityOfThisLL(ret);
2977   return ret.str();
2978 }
2979
2980 /*!
2981  * This method returns a C++ code that is a dump of \a this.
2982  * This method will throw if this is not fully defined.
2983  */
2984 std::string MEDCouplingUMesh::cppRepr() const
2985 {
2986   static const char coordsName[]="coords";
2987   static const char connName[]="conn";
2988   static const char connIName[]="connI";
2989   checkFullyDefined();
2990   std::ostringstream ret; ret << "// coordinates" << std::endl;
2991   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2992   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2993   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2994   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2995   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2996   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2997   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2998   return ret.str();
2999 }
3000
3001 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3002 {
3003   std::ostringstream ret;
3004   reprConnectivityOfThisLL(ret);
3005   return ret.str();
3006 }
3007
3008 /*!
3009  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3010  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3011  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3012  * some algos).
3013  * 
3014  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3015  * 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
3016  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3017  */
3018 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3019 {
3020   int mdim=getMeshDimension();
3021   if(mdim<0)
3022     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3023   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3024   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3025   bool needToCpyCT=true;
3026   if(!_nodal_connec)
3027     {
3028       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3029       needToCpyCT=false;
3030     }
3031   else
3032     {
3033       tmp1=_nodal_connec;
3034       tmp1->incrRef();
3035     }
3036   if(!_nodal_connec_index)
3037     {
3038       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3039       needToCpyCT=false;
3040     }
3041   else
3042     {
3043       tmp2=_nodal_connec_index;
3044       tmp2->incrRef();
3045     }
3046   ret->setConnectivity(tmp1,tmp2,false);
3047   if(needToCpyCT)
3048     ret->_types=_types;
3049   if(!_coords)
3050     {
3051       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3052       ret->setCoords(coords);
3053     }
3054   else
3055     ret->setCoords(_coords);
3056   return ret.retn();
3057 }
3058
3059 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3060 {
3061   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3062     {
3063       int nbOfCells=getNumberOfCells();
3064       const int *c=_nodal_connec->getConstPointer();
3065       const int *ci=_nodal_connec_index->getConstPointer();
3066       for(int i=0;i<nbOfCells;i++)
3067         {
3068           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3069           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3070           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3071           stream << "\n";
3072         }
3073     }
3074   else
3075     stream << "Connectivity not defined !\n";
3076 }
3077
3078 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3079 {
3080   const int *ptI=_nodal_connec_index->getConstPointer();
3081   const int *pt=_nodal_connec->getConstPointer();
3082   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3083     return ptI[cellId+1]-ptI[cellId]-1;
3084   else
3085     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3086 }
3087
3088 /*!
3089  * Returns types of cells of the specified part of \a this mesh.
3090  * This method avoids computing sub-mesh explicitely to get its types.
3091  *  \param [in] begin - an array of cell ids of interest.
3092  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3093  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3094  *         describing the cell types. 
3095  *  \throw If the coordinates array is not set.
3096  *  \throw If the nodal connectivity of cells is not defined.
3097  *  \sa getAllGeoTypes()
3098  */
3099 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3100 {
3101   checkFullyDefined();
3102   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3103   const int *conn=_nodal_connec->getConstPointer();
3104   const int *connIndex=_nodal_connec_index->getConstPointer();
3105   for(const int *w=begin;w!=end;w++)
3106     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3107   return ret;
3108 }
3109
3110 /*!
3111  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3112  * a set of types of cells constituting \a this mesh. 
3113  * This method is for advanced users having prepared their connectivity before. For
3114  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3115  *  \param [in] conn - the nodal connectivity array. 
3116  *  \param [in] connIndex - the nodal connectivity index array.
3117  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3118  *         mesh is updated.
3119  */
3120 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3121 {
3122   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3123   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3124   if(isComputingTypes)
3125     computeTypes();
3126   declareAsNew();
3127 }
3128
3129 /*!
3130  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3131  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3132  */
3133 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3134     _nodal_connec(0),_nodal_connec_index(0),
3135     _types(other._types)
3136 {
3137   if(other._nodal_connec)
3138     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3139   if(other._nodal_connec_index)
3140     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3141 }
3142
3143 MEDCouplingUMesh::~MEDCouplingUMesh()
3144 {
3145   if(_nodal_connec)
3146     _nodal_connec->decrRef();
3147   if(_nodal_connec_index)
3148     _nodal_connec_index->decrRef();
3149 }
3150
3151 /*!
3152  * Recomputes a set of cell types of \a this mesh. For more info see
3153  * \ref MEDCouplingUMeshNodalConnectivity.
3154  */
3155 void MEDCouplingUMesh::computeTypes()
3156 {
3157   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3158 }
3159
3160 /*!
3161  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3162  */
3163 void MEDCouplingUMesh::checkFullyDefined() const
3164 {
3165   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3166     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3167 }
3168
3169 /*!
3170  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3171  */
3172 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3173 {
3174   if(!_nodal_connec_index || !_nodal_connec)
3175     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3176 }
3177
3178 /*!
3179  * Returns a number of cells constituting \a this mesh. 
3180  *  \return int - the number of cells in \a this mesh.
3181  *  \throw If the nodal connectivity of cells is not defined.
3182  */
3183 int MEDCouplingUMesh::getNumberOfCells() const
3184
3185   if(_nodal_connec_index)
3186     return _nodal_connec_index->getNumberOfTuples()-1;
3187   else
3188     if(_mesh_dim==-1)
3189       return 1;
3190     else
3191       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3192 }
3193
3194 /*!
3195  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3196  * mesh. For more info see \ref MEDCouplingMeshesPage.
3197  *  \return int - the dimension of \a this mesh.
3198  *  \throw If the mesh dimension is not defined using setMeshDimension().
3199  */
3200 int MEDCouplingUMesh::getMeshDimension() const
3201 {
3202   if(_mesh_dim<-1)
3203     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3204   return _mesh_dim;
3205 }
3206
3207 /*!
3208  * Returns a length of the nodal connectivity array.
3209  * This method is for test reason. Normally the integer returned is not useable by
3210  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3211  *  \return int - the length of the nodal connectivity array.
3212  */
3213 int MEDCouplingUMesh::getMeshLength() const
3214 {
3215   return _nodal_connec->getNbOfElems();
3216 }
3217
3218 /*!
3219  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3220  */
3221 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3222 {
3223   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3224   tinyInfo.push_back(getMeshDimension());
3225   tinyInfo.push_back(getNumberOfCells());
3226   if(_nodal_connec)
3227     tinyInfo.push_back(getMeshLength());
3228   else
3229     tinyInfo.push_back(-1);
3230 }
3231
3232 /*!
3233  * First step of unserialization process.
3234  */
3235 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3236 {
3237   return tinyInfo[6]<=0;
3238 }
3239
3240 /*!
3241  * Second step of serialization process.
3242  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3243  */
3244 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3245 {
3246   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3247   if(tinyInfo[5]!=-1)
3248     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3249 }
3250
3251 /*!
3252  * Third and final step of serialization process.
3253  */
3254 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3255 {
3256   MEDCouplingPointSet::serialize(a1,a2);
3257   if(getMeshDimension()>-1)
3258     {
3259       a1=DataArrayInt::New();
3260       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3261       int *ptA1=a1->getPointer();
3262       const int *conn=getNodalConnectivity()->getConstPointer();
3263       const int *index=getNodalConnectivityIndex()->getConstPointer();
3264       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3265       std::copy(conn,conn+getMeshLength(),ptA1);
3266     }
3267   else
3268     a1=0;
3269 }
3270
3271 /*!
3272  * Second and final unserialization process.
3273  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3274  */
3275 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3276 {
3277   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3278   setMeshDimension(tinyInfo[5]);
3279   if(tinyInfo[7]!=-1)
3280     {
3281       // Connectivity
3282       const int *recvBuffer=a1->getConstPointer();
3283       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3284       myConnecIndex->alloc(tinyInfo[6]+1,1);
3285       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3286       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3287       myConnec->alloc(tinyInfo[7],1);
3288       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3289       setConnectivity(myConnec, myConnecIndex);
3290     }
3291 }
3292
3293 /*!
3294  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3295  * CellIds are given using range specified by a start an end and step.
3296  */
3297 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3298 {
3299   checkFullyDefined();
3300   int ncell=getNumberOfCells();
3301   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3302   ret->_mesh_dim=_mesh_dim;
3303   ret->setCoords(_coords);
3304   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3305   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3306   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3307   int work=start;
3308   const int *conn=_nodal_connec->getConstPointer();
3309   const int *connIndex=_nodal_connec_index->getConstPointer();
3310   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3311     {
3312       if(work>=0 && work<ncell)
3313         {
3314           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3315         }
3316       else
3317         {
3318           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3319           throw INTERP_KERNEL::Exception(oss.str().c_str());
3320         }
3321     }
3322   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3323   int *newConnPtr=newConn->getPointer();
3324   std::set<INTERP_KERNEL::NormalizedCellType> types;
3325   work=start;
3326   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3327     {
3328       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3329       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3330     }
3331   ret->setConnectivity(newConn,newConnI,false);
3332   ret->_types=types;
3333   ret->copyTinyInfoFrom(this);
3334   return ret.retn();
3335 }
3336
3337 /*!
3338  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3339  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3340  * The return newly allocated mesh will share the same coordinates as \a this.
3341  */
3342 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3343 {
3344   checkConnectivityFullyDefined();
3345   int ncell=getNumberOfCells();
3346   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3347   ret->_mesh_dim=_mesh_dim;
3348   ret->setCoords(_coords);
3349   std::size_t nbOfElemsRet=std::distance(begin,end);
3350   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3351   connIndexRet[0]=0;
3352   const int *conn=_nodal_connec->getConstPointer();
3353   const int *connIndex=_nodal_connec_index->getConstPointer();
3354   int newNbring=0;
3355   for(const int *work=begin;work!=end;work++,newNbring++)
3356     {
3357       if(*work>=0 && *work<ncell)
3358         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3359       else
3360         {
3361           free(connIndexRet);
3362           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3363           throw INTERP_KERNEL::Exception(oss.str().c_str());
3364         }
3365     }
3366   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3367   int *connRetWork=connRet;
3368   std::set<INTERP_KERNEL::NormalizedCellType> types;
3369   for(const int *work=begin;work!=end;work++)
3370     {
3371       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3372       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3373     }
3374   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3375   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3376   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3377   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3378   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3379   ret->_types=types;
3380   ret->copyTinyInfoFrom(this);
3381   return ret.retn();
3382 }
3383
3384 /*!
3385  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3386  * mesh.<br>
3387  * For 1D cells, the returned field contains lengths.<br>
3388  * For 2D cells, the returned field contains areas.<br>
3389  * For 3D cells, the returned field contains volumes.
3390  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3391  *         orientation, i.e. the volume is always positive.
3392  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3393  *         and one time . The caller is to delete this field using decrRef() as it is no
3394  *         more needed.
3395  */
3396 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3397 {
3398   std::string name="MeasureOfMesh_";
3399   name+=getName();
3400   int nbelem=getNumberOfCells();
3401   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3402   field->setName(name);
3403   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3404   array->alloc(nbelem,1);
3405   double *area_vol=array->getPointer();
3406   field->setArray(array) ; array=0;
3407   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3408   field->synchronizeTimeWithMesh();
3409   if(getMeshDimension()!=-1)
3410     {
3411       int ipt;
3412       INTERP_KERNEL::NormalizedCellType type;
3413       int dim_space=getSpaceDimension();
3414       const double *coords=getCoords()->getConstPointer();
3415       const int *connec=getNodalConnectivity()->getConstPointer();
3416       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3417       for(int iel=0;iel<nbelem;iel++)
3418         {
3419           ipt=connec_index[iel];
3420           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3421           area_vol[iel]=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[iel+1]-ipt-1,coords,dim_space);
3422         }
3423       if(isAbs)
3424         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3425     }
3426   else
3427     {
3428       area_vol[0]=std::numeric_limits<double>::max();
3429     }
3430   return field.retn();
3431 }
3432
3433 /*!
3434  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3435  * mesh.<br>
3436  * For 1D cells, the returned array contains lengths.<br>
3437  * For 2D cells, the returned array contains areas.<br>
3438  * For 3D cells, the returned array contains volumes.
3439  * This method avoids building explicitly a part of \a this mesh to perform the work.
3440  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3441  *         orientation, i.e. the volume is always positive.
3442  *  \param [in] begin - an array of cell ids of interest.
3443  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3444  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3445  *          delete this array using decrRef() as it is no more needed.
3446  * 
3447  *  \if ENABLE_EXAMPLES
3448  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3449  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3450  *  \endif
3451  *  \sa getMeasureField()
3452  */
3453 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3454 {
3455   std::string name="PartMeasureOfMesh_";
3456   name+=getName();
3457   int nbelem=(int)std::distance(begin,end);
3458   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3459   array->setName(name);
3460   array->alloc(nbelem,1);
3461   double *area_vol=array->getPointer();
3462   if(getMeshDimension()!=-1)
3463     {
3464       int ipt;
3465       INTERP_KERNEL::NormalizedCellType type;
3466       int dim_space=getSpaceDimension();
3467       const double *coords=getCoords()->getConstPointer();
3468       const int *connec=getNodalConnectivity()->getConstPointer();
3469       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3470       for(const int *iel=begin;iel!=end;iel++)
3471         {
3472           ipt=connec_index[*iel];
3473           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3474           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3475         }
3476       if(isAbs)
3477         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3478     }
3479   else
3480     {
3481       area_vol[0]=std::numeric_limits<double>::max();
3482     }
3483   return array.retn();
3484 }
3485
3486 /*!
3487  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3488  * \a this one. The returned field contains the dual cell volume for each corresponding
3489  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3490  *  the dual mesh in P1 sens of \a this.<br>
3491  * For 1D cells, the returned field contains lengths.<br>
3492  * For 2D cells, the returned field contains areas.<br>
3493  * For 3D cells, the returned field contains volumes.
3494  * This method is useful to check "P1*" conservative interpolators.
3495  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3496  *         orientation, i.e. the volume is always positive.
3497  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3498  *          nodes and one time. The caller is to delete this array using decrRef() as
3499  *          it is no more needed.
3500  */
3501 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3502 {
3503   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3504   std::string name="MeasureOnNodeOfMesh_";
3505   name+=getName();
3506   int nbNodes=getNumberOfNodes();
3507   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3508   double cst=1./((double)getMeshDimension()+1.);
3509   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3510   array->alloc(nbNodes,1);
3511   double *valsToFill=array->getPointer();
3512   std::fill(valsToFill,valsToFill+nbNodes,0.);
3513   const double *values=tmp->getArray()->getConstPointer();
3514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3515   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3516   getReverseNodalConnectivity(da,daInd);
3517   const int *daPtr=da->getConstPointer();
3518   const int *daIPtr=daInd->getConstPointer();
3519   for(int i=0;i<nbNodes;i++)
3520     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3521       valsToFill[i]+=cst*values[*cell];
3522   ret->setMesh(this);
3523   ret->setArray(array);
3524   return ret.retn();
3525 }
3526
3527 /*!
3528  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3529  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3530  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3531  * and are normalized.
3532  * <br> \a this can be either 
3533  * - a  2D mesh in 2D or 3D space or 
3534  * - an 1D mesh in 2D space.
3535  * 
3536  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3537  *          cells and one time. The caller is to delete this field using decrRef() as
3538  *          it is no more needed.
3539  *  \throw If the nodal connectivity of cells is not defined.
3540  *  \throw If the coordinates array is not set.
3541  *  \throw If the mesh dimension is not set.
3542  *  \throw If the mesh and space dimension is not as specified above.
3543  */
3544 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3545 {
3546   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3547     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3548   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3549   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3550   int nbOfCells=getNumberOfCells();
3551   int nbComp=getMeshDimension()+1;
3552   array->alloc(nbOfCells,nbComp);
3553   double *vals=array->getPointer();
3554   const int *connI=_nodal_connec_index->getConstPointer();
3555   const int *conn=_nodal_connec->getConstPointer();
3556   const double *coords=_coords->getConstPointer();
3557   if(getMeshDimension()==2)
3558     {
3559       if(getSpaceDimension()==3)
3560         {
3561           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3562           const double *locPtr=loc->getConstPointer();
3563           for(int i=0;i<nbOfCells;i++,vals+=3)
3564             {
3565               int offset=connI[i];
3566               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3567               double n=INTERP_KERNEL::norm<3>(vals);
3568               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3569             }
3570         }
3571       else
3572         {
3573           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3574           const double *isAbsPtr=isAbs->getArray()->begin();
3575           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3576             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3577         }
3578     }
3579   else//meshdimension==1
3580     {
3581       double tmp[2];
3582       for(int i=0;i<nbOfCells;i++)
3583         {
3584           int offset=connI[i];
3585           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3586           double n=INTERP_KERNEL::norm<2>(tmp);
3587           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3588           *vals++=-tmp[1];
3589           *vals++=tmp[0];
3590         }
3591     }
3592   ret->setArray(array);
3593   ret->setMesh(this);
3594   ret->synchronizeTimeWithSupport();
3595   return ret.retn();
3596 }
3597
3598 /*!
3599  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3600  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3601  * and are normalized.
3602  * <br> \a this can be either 
3603  * - a  2D mesh in 2D or 3D space or 
3604  * - an 1D mesh in 2D space.
3605  * 
3606  * This method avoids building explicitly a part of \a this mesh to perform the work.
3607  *  \param [in] begin - an array of cell ids of interest.
3608  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3609  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3610  *          cells and one time. The caller is to delete this field using decrRef() as
3611  *          it is no more needed.
3612  *  \throw If the nodal connectivity of cells is not defined.
3613  *  \throw If the coordinates array is not set.
3614  *  \throw If the mesh dimension is not set.
3615  *  \throw If the mesh and space dimension is not as specified above.
3616  *  \sa buildOrthogonalField()
3617  *
3618  *  \if ENABLE_EXAMPLES
3619  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3620  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3621  *  \endif
3622  */
3623 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3624 {
3625   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3626     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3627   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3628   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3629   std::size_t nbelems=std::distance(begin,end);
3630   int nbComp=getMeshDimension()+1;
3631   array->alloc((int)nbelems,nbComp);
3632   double *vals=array->getPointer();
3633   const int *connI=_nodal_connec_index->getConstPointer();
3634   const int *conn=_nodal_connec->getConstPointer();
3635   const double *coords=_coords->getConstPointer();
3636   if(getMeshDimension()==2)
3637     {
3638       if(getSpaceDimension()==3)
3639         {
3640           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3641           const double *locPtr=loc->getConstPointer();
3642           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3643             {
3644               int offset=connI[*i];
3645               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3646               double n=INTERP_KERNEL::norm<3>(vals);
3647               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3648             }
3649         }
3650       else
3651         {
3652           for(std::size_t i=0;i<nbelems;i++)
3653             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3654         }
3655     }
3656   else//meshdimension==1
3657     {
3658       double tmp[2];
3659       for(const int *i=begin;i!=end;i++)
3660         {
3661           int offset=connI[*i];
3662           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3663           double n=INTERP_KERNEL::norm<2>(tmp);
3664           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3665           *vals++=-tmp[1];
3666           *vals++=tmp[0];
3667         }
3668     }
3669   ret->setArray(array);
3670   ret->setMesh(this);
3671   ret->synchronizeTimeWithSupport();
3672   return ret.retn();
3673 }
3674
3675 /*!
3676  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3677  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3678  * and are \b not normalized.
3679  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3680  *          cells and one time. The caller is to delete this field using decrRef() as
3681  *          it is no more needed.
3682  *  \throw If the nodal connectivity of cells is not defined.
3683  *  \throw If the coordinates array is not set.
3684  *  \throw If \a this->getMeshDimension() != 1.
3685  *  \throw If \a this mesh includes cells of type other than SEG2.
3686  */
3687 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3688 {
3689   if(getMeshDimension()!=1)
3690     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3691   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3692     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3693   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3694   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3695   int nbOfCells=getNumberOfCells();
3696   int spaceDim=getSpaceDimension();
3697   array->alloc(nbOfCells,spaceDim);
3698   double *pt=array->getPointer();
3699   const double *coo=getCoords()->getConstPointer();
3700   std::vector<int> conn;
3701   conn.reserve(2);
3702   for(int i=0;i<nbOfCells;i++)
3703     {
3704       conn.resize(0);
3705       getNodeIdsOfCell(i,conn);
3706       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3707     }
3708   ret->setArray(array);
3709   ret->setMesh(this);
3710   ret->synchronizeTimeWithSupport();
3711   return ret.retn();
3712 }
3713
3714 /*!
3715  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3716  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3717  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3718  * from. If a result face is shared by two 3D cells, then the face in included twice in
3719  * the result mesh.
3720  *  \param [in] origin - 3 components of a point defining location of the plane.
3721  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3722  *         must be greater than 1e-6.
3723  *  \param [in] eps - half-thickness of the plane.
3724  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3725  *         producing correspondent 2D cells. The caller is to delete this array
3726  *         using decrRef() as it is no more needed.
3727  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3728  *         not share the node coordinates array with \a this mesh. The caller is to
3729  *         delete this mesh using decrRef() as it is no more needed.  
3730  *  \throw If the coordinates array is not set.
3731  *  \throw If the nodal connectivity of cells is not defined.
3732  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3733  *  \throw If magnitude of \a vec is less than 1e-6.
3734  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3735  *  \throw If \a this includes quadratic cells.
3736  */
3737 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3738 {
3739   checkFullyDefined();
3740   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3741     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3742   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3743   if(candidates->empty())
3744     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3745   std::vector<int> nodes;
3746   DataArrayInt *cellIds1D=0;
3747   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3748   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3749   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3750   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3751   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3752   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3753   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3754   revDesc2=0; revDescIndx2=0;
3755   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3756   revDesc1=0; revDescIndx1=0;
3757   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3758   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3759   //
3760   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3761   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3762     cut3DCurve[*it]=-1;
3763   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3764   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3765   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3766                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3767                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3768   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3769   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3770   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3771   if(cellIds2->empty())
3772     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3773   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3774   ret->setCoords(mDesc1->getCoords());
3775   ret->setConnectivity(conn,connI,true);
3776   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3777   return ret.retn();
3778 }
3779
3780 /*!
3781  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3782 addition to the mesh, returns a new DataArrayInt, of length equal to the number of 1D cells in the result mesh, holding, for each cell in the result mesh, an id of a 2D cell it comes
3783 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3784 the result mesh.
3785  *  \param [in] origin - 3 components of a point defining location of the plane.
3786  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3787  *         must be greater than 1e-6.
3788  *  \param [in] eps - half-thickness of the plane.
3789  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3790  *         producing correspondent segments. The caller is to delete this array
3791  *         using decrRef() as it is no more needed.
3792  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3793  *         mesh in 3D space. This mesh does not share the node coordinates array with
3794  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3795  *         no more needed. 
3796  *  \throw If the coordinates array is not set.
3797  *  \throw If the nodal connectivity of cells is not defined.
3798  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3799  *  \throw If magnitude of \a vec is less than 1e-6.
3800  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3801  *  \throw If \a this includes quadratic cells.
3802  */
3803 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3804 {
3805   checkFullyDefined();
3806   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3807     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3808   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3809   if(candidates->empty())
3810     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3811   std::vector<int> nodes;
3812   DataArrayInt *cellIds1D=0;
3813   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3814   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3815   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3816   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3817   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3818   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3819   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3820   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3822   //
3823   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3824   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3825     cut3DCurve[*it]=-1;
3826   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3827   int ncellsSub=subMesh->getNumberOfCells();
3828   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3829   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3830                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3831                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3832   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3833   conn->alloc(0,1);
3834   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3835   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3836   for(int i=0;i<ncellsSub;i++)
3837     {
3838       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3839         {
3840           if(cut3DSurf[i].first!=-2)
3841             {
3842               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3843               connI->pushBackSilent(conn->getNumberOfTuples());
3844               cellIds2->pushBackSilent(i);
3845             }
3846           else
3847             {
3848               int cellId3DSurf=cut3DSurf[i].second;
3849               int offset=nodalI[cellId3DSurf]+1;
3850               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3851               for(int j=0;j<nbOfEdges;j++)
3852                 {
3853                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3854                   connI->pushBackSilent(conn->getNumberOfTuples());
3855                   cellIds2->pushBackSilent(cellId3DSurf);
3856                 }
3857             }
3858         }
3859     }
3860   if(cellIds2->empty())
3861     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3862   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3863   ret->setCoords(mDesc1->getCoords());
3864   ret->setConnectivity(conn,connI,true);
3865   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3866   return ret.retn();
3867 }
3868
3869 /*!
3870  * Finds cells whose bounding boxes intersect a given plane.
3871  *  \param [in] origin - 3 components of a point defining location of the plane.
3872  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3873  *         must be greater than 1e-6.
3874  *  \param [in] eps - half-thickness of the plane.
3875  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3876  *         cells. The caller is to delete this array using decrRef() as it is no more
3877  *         needed.
3878  *  \throw If the coordinates array is not set.
3879  *  \throw If the nodal connectivity of cells is not defined.
3880  *  \throw If \a this->getSpaceDimension() != 3.
3881  *  \throw If magnitude of \a vec is less than 1e-6.
3882  *  \sa buildSlice3D()
3883  */
3884 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3885 {
3886   checkFullyDefined();
3887   if(getSpaceDimension()!=3)
3888     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3889   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3890   if(normm<1e-6)
3891     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3892   double vec2[3];
3893   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3894   double angle=acos(vec[2]/normm);
3895   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3896   double bbox[6];
3897   if(angle>eps)
3898     {
3899       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3900       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3901       if(normm2/normm>1e-6)
3902         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3903       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3904       mw->setCoords(coo);
3905       mw->getBoundingBox(bbox);
3906       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3907       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3908     }
3909   else
3910     {
3911       getBoundingBox(bbox);
3912       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3913       cellIds=getCellsInBoundingBox(bbox,eps);
3914     }
3915   return cellIds.retn();
3916 }
3917
3918 /*!
3919  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3920  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3921  * No consideration of coordinate is done by this method.
3922  * A 1D mesh is said contiguous if : a cell i with nodal connectivity (k,p) the cell i+1 the nodal connectivity should be (p,m)
3923  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3924  */
3925 bool MEDCouplingUMesh::isContiguous1D() const
3926 {
3927   if(getMeshDimension()!=1)
3928     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3929   int nbCells=getNumberOfCells();
3930   if(nbCells<1)
3931     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3932   const int *connI=_nodal_connec_index->getConstPointer();
3933   const int *conn=_nodal_connec->getConstPointer();
3934   int ref=conn[connI[0]+2];
3935   for(int i=1;i<nbCells;i++)
3936     {
3937       if(conn[connI[i]+1]!=ref)
3938         return false;
3939       ref=conn[connI[i]+2];
3940     }
3941   return true;
3942 }
3943
3944 /*!
3945  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3946  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3947  * \param pt reference point of the line
3948  * \param v normalized director vector of the line
3949  * \param eps max precision before throwing an exception
3950  * \param res output of size this->getNumberOfCells
3951  */
3952 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3953 {
3954   if(getMeshDimension()!=1)
3955     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3956   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3957     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3958   if(getSpaceDimension()!=3)
3959     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3960   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3961   const double *fPtr=f->getArray()->getConstPointer();
3962   double tmp[3];
3963   for(int i=0;i<getNumberOfCells();i++)
3964     {
3965       const double *tmp1=fPtr+3*i;
3966       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3967       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3968       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3969       double n1=INTERP_KERNEL::norm<3>(tmp);
3970       n1/=INTERP_KERNEL::norm<3>(tmp1);
3971       if(n1>eps)
3972         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3973     }
3974   const double *coo=getCoords()->getConstPointer();
3975   for(int i=0;i<getNumberOfNodes();i++)
3976     {
3977       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3978       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3979       res[i]=std::accumulate(tmp,tmp+3,0.);
3980     }
3981 }
3982
3983 /*!
3984  * This method computes the distance from a point \a pt to \a this and the first \a cellId in \a this corresponding to the returned distance. 
3985  * \a this is expected to be a mesh so that its space dimension is equal to its
3986  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3987  * Distance from \a ptBg to \a ptEnd is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
3988  *
3989  * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3990  * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3991  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3992  *
3993  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3994  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3995  *
3996  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3997  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3998  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3999  * \return the positive value of the distance.
4000  * \throw if distance from \a ptBg to \a ptEnd is not equal to the space dimension. An exception is also thrown if mesh dimension of \a this is not equal to space
4001  * dimension - 1.
4002  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4003  */
4004 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4005 {
4006   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4007   if(meshDim!=spaceDim-1)
4008     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4009   if(meshDim!=2 && meshDim!=1)
4010     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4011   checkFullyDefined();
4012   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4013     { std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoint : input point has to have dimension equal to the space dimension of this (" << spaceDim << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
4014   DataArrayInt *ret1=0;
4015   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4016   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4017   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4018   cellId=*ret1Safe->begin();
4019   return *ret0->begin();
4020 }
4021
4022 /*!
4023  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4024  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4025  * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
4026  * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
4027  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4028  * 
4029  * \a this is expected to be a mesh so that its space dimension is equal to its
4030  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4031  * Number of components of \a pts is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
4032  *
4033  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4034  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4035  *
4036  * \param [in] pts the list of points in which each tuple represents a point
4037  * \param [out] cellIds a newly allocated object that tells for each point in \a pts the first cell id in \a this that minimizes the distance.
4038  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4039  * \throw if number of components of \a pts is not equal to the space dimension.
4040  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4041  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4042  */
4043 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4044 {
4045   if(!pts)
4046     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4047   pts->checkAllocated();
4048   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4049   if(meshDim!=spaceDim-1)
4050     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4051   if(meshDim!=2 && meshDim!=1)
4052     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4053   if(pts->getNumberOfComponents()!=spaceDim)
4054     {
4055       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4056       throw INTERP_KERNEL::Exception(oss.str().c_str());
4057     }
4058   checkFullyDefined();
4059   int nbCells=getNumberOfCells();
4060   if(nbCells==0)
4061     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4062   int nbOfPts=pts->getNumberOfTuples();
4063   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4064   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4065   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4066   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4067   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4068   const double *bbox(bboxArr->begin());
4069   switch(spaceDim)
4070   {
4071     case 3:
4072       {
4073         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4074         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4075           {
4076             double x=std::numeric_limits<double>::max();
4077             std::vector<int> elems;
4078             myTree.getMinDistanceOfMax(ptsPtr,x);
4079             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4080             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4081           }
4082         break;
4083       }
4084     case 2:
4085       {
4086         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4087         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4088           {
4089             double x=std::numeric_limits<double>::max();
4090             std::vector<int> elems;
4091             myTree.getMinDistanceOfMax(ptsPtr,x);
4092             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4093             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4094           }
4095         break;
4096       }
4097     default:
4098       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4099   }
4100   cellIds=ret1.retn();
4101   return ret0.retn();
4102 }
4103
4104 /*!
4105  * \param [in] pt the start pointer (included) of the coordinates of the point
4106  * \param [in] cellIdsBg the start pointer (included) of cellIds
4107  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4108  * \param [in] nc nodal connectivity
4109  * \param [in] ncI nodal connectivity index
4110  * \param [in,out] ret0 the min distance between \a this and the external input point
4111  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4112  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4113  */
4114 void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId)
4115 {
4116   cellId=-1;
4117   ret0=std::numeric_limits<double>::max();
4118   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4119     {
4120       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4121       {
4122         case INTERP_KERNEL::NORM_TRI3:
4123           {
4124             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4125             if(tmp<ret0)
4126               { ret0=tmp; cellId=*zeCell; }
4127             break;
4128           }
4129         case INTERP_KERNEL::NORM_QUAD4:
4130         case INTERP_KERNEL::NORM_POLYGON:
4131           {
4132             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4133             if(tmp<ret0)
4134               { ret0=tmp; cellId=*zeCell; }
4135             break;
4136           }
4137         default:
4138           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4139       }
4140     }
4141 }
4142
4143 /*!
4144  * \param [in] pt the start pointer (included) of the coordinates of the point
4145  * \param [in] cellIdsBg the start pointer (included) of cellIds
4146  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4147  * \param [in] nc nodal connectivity
4148  * \param [in] ncI nodal connectivity index
4149  * \param [in,out] ret0 the min distance between \a this and the external input point
4150  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4151  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4152  */
4153 void MEDCouplingUMesh::DistanceToPoint2DCurveAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId)
4154 {
4155   cellId=-1;
4156   ret0=std::numeric_limits<double>::max();
4157   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4158     {
4159       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4160       {
4161         case INTERP_KERNEL::NORM_SEG2:
4162           {
4163             std::size_t uselessEntry=0;
4164             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4165             tmp=sqrt(tmp);
4166             if(tmp<ret0)
4167               { ret0=tmp; cellId=*zeCell; }
4168             break;
4169           }
4170         default:
4171           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4172       }
4173     }
4174 }
4175
4176 /*!
4177  * Finds cells in contact with a ball (i.e. a point with precision). 
4178  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4179  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4180  *
4181  * \warning This method is suitable if the caller intends to evaluate only one
4182  *          point, for more points getCellsContainingPoints() is recommended as it is
4183  *          faster. 
4184  *  \param [in] pos - array of coordinates of the ball central point.
4185  *  \param [in] eps - ball radius.
4186  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4187  *         if there are no such cells.
4188  *  \throw If the coordinates array is not set.
4189  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4190  */
4191 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4192 {
4193   std::vector<int> elts;
4194   getCellsContainingPoint(pos,eps,elts);
4195   if(elts.empty())
4196     return -1;
4197   return elts.front();
4198 }
4199
4200 /*!
4201  * Finds cells in contact with a ball (i.e. a point with precision).
4202  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4203  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4204  * \warning This method is suitable if the caller intends to evaluate only one
4205  *          point, for more points getCellsContainingPoints() is recommended as it is
4206  *          faster. 
4207  *  \param [in] pos - array of coordinates of the ball central point.
4208  *  \param [in] eps - ball radius.
4209  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4210  *         before inserting ids.
4211  *  \throw If the coordinates array is not set.
4212  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4213  *
4214  *  \if ENABLE_EXAMPLES
4215  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4216  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4217  *  \endif
4218  */
4219 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4220 {
4221   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4222   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4223   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4224 }
4225
4226 /// @cond INTERNAL
4227
4228 namespace ParaMEDMEM
4229 {
4230   template<const int SPACEDIMM>
4231   class DummyClsMCUG
4232   {
4233   public:
4234     static const int MY_SPACEDIM=SPACEDIMM;
4235     static const int MY_MESHDIM=8;
4236     typedef int MyConnType;
4237     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4238     // begin
4239     // useless, but for windows compilation ...
4240     const double* getCoordinatesPtr() const { return 0; }
4241     const int* getConnectivityPtr() const { return 0; }
4242     const int* getConnectivityIndexPtr() const { return 0; }
4243     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4244     // end
4245   };
4246
4247   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4248   {
4249     INTERP_KERNEL::Edge *ret(0);
4250     MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1]));
4251     m[n0]=bg[0]; m[n1]=bg[1];
4252     switch(typ)
4253     {
4254       case INTERP_KERNEL::NORM_SEG2:
4255         {
4256           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4257           break;
4258         }
4259       case INTERP_KERNEL::NORM_SEG3:
4260         {
4261           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4262           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4263           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4264           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4265           bool colinearity(inters.areColinears());
4266           delete e1; delete e2;
4267           if(colinearity)
4268             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4269           else
4270             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4271           break;
4272         }
4273       default:
4274         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4275     }
4276     return ret;
4277   }
4278
4279   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4280   {
4281     INTERP_KERNEL::Edge *ret=0;
4282     switch(typ)
4283     {
4284       case INTERP_KERNEL::NORM_SEG2:
4285         {
4286           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4287           break;
4288         }
4289       case INTERP_KERNEL::NORM_SEG3:
4290         {
4291           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4292           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4293           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4294           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4295           bool colinearity=inters.areColinears();
4296           delete e1; delete e2;
4297           if(colinearity)
4298             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4299           else
4300             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4301           mapp2[bg[2]].second=false;
4302           break;
4303         }
4304       default:
4305         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4306     }
4307     return ret;
4308   }
4309
4310   /*!
4311    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4312    * the global mesh 'mDesc'.
4313    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4314    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4315    */
4316   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4317                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4318   {
4319     mapp.clear();
4320     std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;//bool is for a flag specifying if node is boundary (true) or only a middle for SEG3.
4321     const double *coo=mDesc->getCoords()->getConstPointer();
4322     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4323     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4324     std::set<int> s;
4325     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4326       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4327     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4328       {
4329         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4330         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4331       }
4332     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4333     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4334       {
4335         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4336         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4337       }
4338     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4339       {
4340         if((*it2).second.second)
4341           mapp[(*it2).second.first]=(*it2).first;
4342         ((*it2).second.first)->decrRef();
4343       }
4344     return ret;
4345   }
4346
4347   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4348   {
4349     if(nodeId>=offset2)
4350       {
4351         int locId=nodeId-offset2;
4352         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4353       }
4354     if(nodeId>=offset1)
4355       {
4356         int locId=nodeId-offset1;
4357         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4358       }
4359     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4360   }
4361
4362   /**
4363    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4364    */
4365   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4366                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4367                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4368   {
4369     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4370       {
4371         int eltId1=abs(*desc1)-1;
4372         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4373           {
4374             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4375             if(it==mappRev.end())
4376               {
4377                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4378                 mapp[node]=*it1;
4379                 mappRev[*it1]=node;
4380               }
4381           }
4382       }
4383   }
4384 }
4385
4386 /// @endcond
4387
4388 template<int SPACEDIM>
4389 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4390                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4391 {
4392   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4393   int *eltsIndexPtr(eltsIndex->getPointer());
4394   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4395   const double *bbox(bboxArr->begin());
4396   int nbOfCells=getNumberOfCells();
4397   const int *conn=_nodal_connec->getConstPointer();
4398   const int *connI=_nodal_connec_index->getConstPointer();
4399   double bb[2*SPACEDIM];
4400   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4401   for(int i=0;i<nbOfPoints;i++)
4402     {
4403       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4404       for(int j=0;j<SPACEDIM;j++)
4405         {
4406           bb[2*j]=pos[SPACEDIM*i+j];
4407           bb[2*j+1]=pos[SPACEDIM*i+j];
4408         }
4409       std::vector<int> candidates;
4410       myTree.getIntersectingElems(bb,candidates);
4411       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4412         {
4413           int sz(connI[(*iter)+1]-connI[*iter]-1);
4414           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4415           bool status(false);
4416           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4417             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4418           else
4419             {
4420               if(SPACEDIM!=2)
4421                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4422               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4423               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4424               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4425               INTERP_KERNEL::QuadraticPolygon *pol(0);
4426               for(int j=0;j<sz;j++)
4427                 {
4428                   int nodeId(conn[connI[*iter]+1+j]);
4429                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4430                 }
4431               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4432                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4433               else
4434                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4435               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4436               double a(0.),b(0.),c(0.);
4437               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4438               status=pol->isInOrOut2(n);
4439               delete pol; n->decrRef();
4440             }
4441           if(status)
4442             {
4443               eltsIndexPtr[i+1]++;
4444               elts->pushBackSilent(*iter);
4445             }
4446         }
4447     }
4448 }
4449 /*!
4450  * Finds cells in contact with several balls (i.e. points with precision).
4451  * This method is an extension of getCellContainingPoint() and
4452  * getCellsContainingPoint() for the case of multiple points.
4453  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4454  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4455  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4456  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4457  *         this->getSpaceDimension() * \a nbOfPoints 
4458  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4459  *  \param [in] eps - radius of balls (i.e. the precision).
4460  *  \param [out] elts - vector returning ids of found cells.
4461  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4462  *         dividing cell ids in \a elts into groups each referring to one
4463  *         point. Its every element (except the last one) is an index pointing to the
4464  *         first id of a group of cells. For example cells in contact with the *i*-th
4465  *         point are described by following range of indices:
4466  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4467  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4468  *         Number of cells in contact with the *i*-th point is
4469  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4470  *  \throw If the coordinates array is not set.
4471  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4472  *
4473  *  \if ENABLE_EXAMPLES
4474  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4475  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4476  *  \endif
4477  */
4478 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4479                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4480 {
4481   int spaceDim=getSpaceDimension();
4482   int mDim=getMeshDimension();
4483   if(spaceDim==3)
4484     {
4485       if(mDim==3)
4486         {
4487           const double *coords=_coords->getConstPointer();
4488           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4489         }
4490       /*else if(mDim==2)
4491         {
4492
4493         }*/
4494       else
4495         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4496     }
4497   else if(spaceDim==2)
4498     {
4499       if(mDim==2)
4500         {
4501           const double *coords=_coords->getConstPointer();
4502           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4503         }
4504       else
4505         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4506     }
4507   else if(spaceDim==1)
4508     {
4509       if(mDim==1)
4510         {
4511           const double *coords=_coords->getConstPointer();
4512           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4513         }
4514       else
4515         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4516     }
4517   else
4518     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4519 }
4520
4521 /*!
4522  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4523  * least two its edges intersect each other anywhere except their extremities. An
4524  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4525  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4526  *         cleared before filling in.
4527  *  \param [in] eps - precision.
4528  *  \throw If \a this->getMeshDimension() != 2.
4529  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4530  */
4531 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4532 {
4533   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4534   if(getMeshDimension()!=2)
4535     throw INTERP_KERNEL::Exception(msg);
4536   int spaceDim=getSpaceDimension();
4537   if(spaceDim!=2 && spaceDim!=3)
4538     throw INTERP_KERNEL::Exception(msg);
4539   const int *conn=_nodal_connec->getConstPointer();
4540   const int *connI=_nodal_connec_index->getConstPointer();
4541   int nbOfCells=getNumberOfCells();
4542   std::vector<double> cell2DinS2;
4543   for(int i=0;i<nbOfCells;i++)
4544     {
4545       int offset=connI[i];
4546       int nbOfNodesForCell=connI[i+1]-offset-1;
4547       if(nbOfNodesForCell<=3)
4548         continue;
4549       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4550       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4551       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4552         cells.push_back(i);
4553       cell2DinS2.clear();
4554     }
4555 }
4556
4557 /*!
4558  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4559  *
4560  * This method expects that space dimension is equal to 2 and mesh dimension is equal to 2 too. If it is not the case an INTERP_KERNEL::Exception will be thrown.
4561  * This method works only for linear 2D cells. If there is any of non linear cells (INTERP_KERNEL::NORM_QUAD8 for example) an INTERP_KERNEL::Exception will be thrown too.
4562  * 
4563  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4564  * This convex envelop is computed using Jarvis march algorithm.
4565  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4566  * Only connectivity of some cells could be modified if those cells were not representing a convex envelop. If a cell already equals its convex envelop (regardless orientation)
4567  * its connectivity will remain unchanged. If the computation leads to a modification of nodal connectivity of a cell its geometric type will be modified to INTERP_KERNEL::NORM_POLYGON.
4568  *
4569  * \return a newly allocated array containing cellIds that have been modified if any. If no cells have been impacted by this method NULL is returned.
4570  * \sa MEDCouplingUMesh::colinearize2D
4571  */
4572 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4573 {
4574   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4575     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4576   checkFullyDefined();
4577   const double *coords=getCoords()->getConstPointer();
4578   int nbOfCells=getNumberOfCells();
4579   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4580   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4581   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4582   int *workIndexOut=nodalConnecIndexOut->getPointer();
4583   *workIndexOut=0;
4584   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4585   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4586   std::set<INTERP_KERNEL::NormalizedCellType> types;
4587   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4588   isChanged->alloc(0,1);
4589   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4590     {
4591       int pos=nodalConnecOut->getNumberOfTuples();
4592       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4593         isChanged->pushBackSilent(i);
4594       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4595       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4596     }
4597   if(isChanged->empty())
4598     return 0;
4599   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4600   _types=types;
4601   return isChanged.retn();
4602 }
4603
4604 /*!
4605  * This method is \b NOT const because it can modify \a this.
4606  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4607  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4608  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4609  * \b 1 for translation and rotation around point of 'mesh1D'.
4610  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4611  */
4612 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4613 {
4614   checkFullyDefined();
4615   mesh1D->checkFullyDefined();
4616   if(!mesh1D->isContiguous1D())
4617     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4618   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4619     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4620   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4621     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4622   if(mesh1D->getMeshDimension()!=1)
4623     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4624   bool isQuad=false;
4625   if(isPresenceOfQuadratic())
4626     {
4627       if(mesh1D->isFullyQuadratic())
4628         isQuad=true;
4629       else
4630         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4631     }
4632   int oldNbOfNodes(getNumberOfNodes());
4633   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4634   switch(policy)
4635   {
4636     case 0:
4637       {
4638         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4639         break;
4640       }
4641     case 1:
4642       {
4643         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4644         break;
4645       }
4646     default:
4647       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4648   }
4649   setCoords(newCoords);
4650   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4651   updateTime();
4652   return ret.retn();
4653 }
4654
4655 /*!
4656  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4657  * If it is not the case an exception will be thrown.
4658  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4659  * intersection of plane defined by ('origin','vec').
4660  * This method has one in/out parameter : 'cut3DCurve'.
4661  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4662  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4663  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4664  * This method will throw an exception if \a this contains a non linear segment.
4665  */
4666 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4667 {
4668   checkFullyDefined();
4669   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4670     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4671   int ncells=getNumberOfCells();
4672   int nnodes=getNumberOfNodes();
4673   double vec2[3],vec3[3],vec4[3];
4674   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4675   if(normm<1e-6)
4676     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4677   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4678   const int *conn=_nodal_connec->getConstPointer();
4679   const int *connI=_nodal_connec_index->getConstPointer();
4680   const double *coo=_coords->getConstPointer();
4681   std::vector<double> addCoo;
4682   for(int i=0;i<ncells;i++)
4683     {
4684       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4685         {
4686           if(cut3DCurve[i]==-2)
4687             {
4688               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4689               vec3[0]=coo[3*endd]-coo[3*st]; vec3[1]=coo[3*endd+1]-coo[3*st+1]; vec3[2]=coo[3*endd+2]-coo[3*st+2];
4690               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4691               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4692               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4693                 {
4694                   const double *st2=coo+3*st;
4695                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4696                   double pos=-(vec4[0]*vec2[0]+vec4[1]*vec2[1]+vec4[2]*vec2[2])/((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2]));
4697                   if(pos>eps && pos<1-eps)
4698                     {
4699                       int nNode=((int)addCoo.size())/3;
4700                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4701                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4702                       cut3DCurve[i]=nnodes+nNode;
4703                     }
4704                 }
4705             }
4706         }
4707       else
4708         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4709     }
4710   if(!addCoo.empty())
4711     {
4712       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4713       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4714       coo2->alloc(newNbOfNodes,3);
4715       double *tmp=coo2->getPointer();
4716       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4717       std::copy(addCoo.begin(),addCoo.end(),tmp);
4718       DataArrayDouble::SetArrayIn(coo2,_coords);
4719     }
4720 }
4721
4722 /*!
4723  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4724  * \param mesh1D is the input 1D mesh used for translation computation.
4725  * \return newCoords new coords filled by this method. 
4726  */
4727 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4728 {
4729   int oldNbOfNodes=getNumberOfNodes();
4730   int nbOf1DCells=mesh1D->getNumberOfCells();
4731   int spaceDim=getSpaceDimension();
4732   DataArrayDouble *ret=DataArrayDouble::New();
4733   std::vector<bool> isQuads;
4734   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4735   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4736   double *retPtr=ret->getPointer();
4737   const double *coords=getCoords()->getConstPointer();
4738   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4739   std::vector<int> v;
4740   std::vector<double> c;
4741   double vec[3];
4742   v.reserve(3);
4743   c.reserve(6);
4744   for(int i=0;i<nbOf1DCells;i++)
4745     {
4746       v.resize(0);
4747       mesh1D->getNodeIdsOfCell(i,v);
4748       c.resize(0);
4749       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4750       mesh1D->getCoordinatesOfNode(v[0],c);
4751       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4752       for(int j=0;j<oldNbOfNodes;j++)
4753         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4754       if(isQuad)
4755         {
4756           c.resize(0);
4757           mesh1D->getCoordinatesOfNode(v[1],c);
4758           mesh1D->getCoordinatesOfNode(v[0],c);
4759           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4760           for(int j=0;j<oldNbOfNodes;j++)
4761             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4762         }
4763     }
4764   ret->copyStringInfoFrom(*getCoords());
4765   return ret;
4766 }
4767
4768 /*!
4769  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4770  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4771  * \return newCoords new coords filled by this method. 
4772  */
4773 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4774 {
4775   if(mesh1D->getSpaceDimension()==2)
4776     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4777   if(mesh1D->getSpaceDimension()==3)
4778     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4779   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4780 }
4781
4782 /*!
4783  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4784  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4785  * \return newCoords new coords filled by this method. 
4786  */
4787 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4788 {
4789   if(isQuad)
4790     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4791   int oldNbOfNodes=getNumberOfNodes();
4792   int nbOf1DCells=mesh1D->getNumberOfCells();
4793   if(nbOf1DCells<2)
4794     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4795   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4796   int nbOfLevsInVec=nbOf1DCells+1;
4797   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4798   double *retPtr=ret->getPointer();
4799   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4800   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4801   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4802   tmp->setCoords(tmp2);
4803   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4804   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4805   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4806   for(int i=1;i<nbOfLevsInVec;i++)
4807     {
4808       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4809       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4810       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4811       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4812       tmp->translate(vec);
4813       double tmp3[2],radius,alpha,alpha0;
4814       const double *p0=i+1<nbOfLevsInVec?begin:third;
4815       const double *p1=i+1<nbOfLevsInVec?end:begin;
4816       const double *p2=i+1<nbOfLevsInVec?third:end;
4817       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4818       double cosangle=i+1<nbOfLevsInVec?(p0[0]-tmp3[0])*(p1[0]-tmp3[0])+(p0[1]-tmp3[1])*(p1[1]-tmp3[1]):(p2[0]-tmp3[0])*(p1[0]-tmp3[0])+(p2[1]-tmp3[1])*(p1[1]-tmp3[1]);
4819       double angle=acos(cosangle/(radius*radius));
4820       tmp->rotate(end,0,angle);
4821       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4822     }
4823   return ret.retn();
4824 }
4825
4826 /*!
4827  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4828  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4829  * \return newCoords new coords filled by this method. 
4830  */
4831 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4832 {
4833   if(isQuad)
4834     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4835   int oldNbOfNodes=getNumberOfNodes();
4836   int nbOf1DCells=mesh1D->getNumberOfCells();
4837   if(nbOf1DCells<2)
4838     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4839   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4840   int nbOfLevsInVec=nbOf1DCells+1;
4841   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4842   double *retPtr=ret->getPointer();
4843   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4844   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4845   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4846   tmp->setCoords(tmp2);
4847   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4848   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4849   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4850   for(int i=1;i<nbOfLevsInVec;i++)
4851     {
4852       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4853       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4854       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4855       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4856       tmp->translate(vec);
4857       double tmp3[2],radius,alpha,alpha0;
4858       const double *p0=i+1<nbOfLevsInVec?begin:third;
4859       const double *p1=i+1<nbOfLevsInVec?end:begin;
4860       const double *p2=i+1<nbOfLevsInVec?third:end;
4861       double vecPlane[3]={
4862         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4863         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4864         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4865       };
4866       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4867       if(norm>1.e-7)
4868         {
4869           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4870           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4871           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4872           double s2=norm2;
4873           double c2=cos(asin(s2));
4874           double m[3][3]={
4875             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4876             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4877             {-vec2[1]*s2, vec2[0]*s2, c2}
4878           };
4879           double p0r[3]={m[0][0]*p0[0]+m[0][1]*p0[1]+m[0][2]*p0[2], m[1][0]*p0[0]+m[1][1]*p0[1]+m[1][2]*p0[2], m[2][0]*p0[0]+m[2][1]*p0[1]+m[2][2]*p0[2]};
4880           double p1r[3]={m[0][0]*p1[0]+m[0][1]*p1[1]+m[0][2]*p1[2], m[1][0]*p1[0]+m[1][1]*p1[1]+m[1][2]*p1[2], m[2][0]*p1[0]+m[2][1]*p1[1]+m[2][2]*p1[2]};
4881           double p2r[3]={m[0][0]*p2[0]+m[0][1]*p2[1]+m[0][2]*p2[2], m[1][0]*p2[0]+m[1][1]*p2[1]+m[1][2]*p2[2], m[2][0]*p2[0]+m[2][1]*p2[1]+m[2][2]*p2[2]};
4882           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4883           double cosangle=i+1<nbOfLevsInVec?(p0r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p0r[1]-tmp3[1])*(p1r[1]-tmp3[1]):(p2r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p2r[1]-tmp3[1])*(p1r[1]-tmp3[1]);
4884           double angle=acos(cosangle/(radius*radius));
4885           tmp->rotate(end,vecPlane,angle);
4886         }
4887       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4888     }
4889   return ret.retn();
4890 }
4891
4892 /*!
4893  * This method is private because not easy to use for end user. This method is const contrary to
4894  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4895  * the coords sorted slice by slice.
4896  * \param isQuad specifies presence of quadratic cells.
4897  */
4898 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4899 {
4900   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4901   int nbOf2DCells(getNumberOfCells());
4902   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4903   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4904   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4905   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4906   newConnI->alloc(nbOf3DCells+1,1);
4907   int *newConnIPtr(newConnI->getPointer());
4908   *newConnIPtr++=0;
4909   std::vector<int> newc;
4910   for(int j=0;j<nbOf2DCells;j++)
4911     {
4912       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4913       *newConnIPtr++=(int)newc.size();
4914     }
4915   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4916   int *newConnPtr(newConn->getPointer());
4917   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4918   newConnIPtr=newConnI->getPointer();
4919   for(int iz=0;iz<nbOf1DCells;iz++)
4920     {
4921       if(iz!=0)
4922         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4923       const int *posOfTypeOfCell(newConnIPtr);
4924       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4925         {
4926           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4927           if(icell!=*posOfTypeOfCell)
4928             {
4929               if(*iter!=-1)
4930                 *newConnPtr=(*iter)+iz*deltaPerLev;
4931               else
4932                 *newConnPtr=-1;
4933             }
4934           else
4935             {
4936               *newConnPtr=*iter;
4937               posOfTypeOfCell++;
4938             }
4939         }
4940     }
4941   ret->setConnectivity(newConn,newConnI,true);
4942   ret->setCoords(getCoords());
4943   return ret;
4944 }
4945
4946 /*!
4947  * Checks if \a this mesh is constituted by only quadratic cells.
4948  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4949  *  \throw If the coordinates array is not set.
4950  *  \throw If the nodal connectivity of cells is not defined.
4951  */
4952 bool MEDCouplingUMesh::isFullyQuadratic() const
4953 {
4954   checkFullyDefined();
4955   bool ret=true;
4956   int nbOfCells=getNumberOfCells();
4957   for(int i=0;i<nbOfCells && ret;i++)
4958     {
4959       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4960       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4961       ret=cm.isQuadratic();
4962     }
4963   return ret;
4964 }
4965
4966 /*!
4967  * Checks if \a this mesh includes any quadratic cell.
4968  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4969  *  \throw If the coordinates array is not set.
4970  *  \throw If the nodal connectivity of cells is not defined.
4971  */
4972 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4973 {
4974   checkFullyDefined();
4975   bool ret=false;
4976   int nbOfCells=getNumberOfCells();
4977   for(int i=0;i<nbOfCells && !ret;i++)
4978     {
4979       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4980       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4981       ret=cm.isQuadratic();
4982     }
4983   return ret;
4984 }
4985
4986 /*!
4987  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4988  * this mesh, it remains unchanged.
4989  *  \throw If the coordinates array is not set.
4990  *  \throw If the nodal connectivity of cells is not defined.
4991  */
4992 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4993 {
4994   checkFullyDefined();
4995   int nbOfCells=getNumberOfCells();
4996   int delta=0;
4997   const int *iciptr=_nodal_connec_index->getConstPointer();
4998   for(int i=0;i<nbOfCells;i++)
4999     {
5000       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5001       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5002       if(cm.isQuadratic())
5003         {
5004           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5005           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5006           if(!cml.isDynamic())
5007             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5008           else
5009             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5010         }
5011     }
5012   if(delta==0)
5013     return ;
5014   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5015   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5016   const int *icptr=_nodal_connec->getConstPointer();
5017   newConn->alloc(getMeshLength()-delta,1);
5018   newConnI->alloc(nbOfCells+1,1);
5019   int *ocptr=newConn->getPointer();
5020   int *ociptr=newConnI->getPointer();
5021   *ociptr=0;
5022   _types.clear();
5023   for(int i=0;i<nbOfCells;i++,ociptr++)
5024     {
5025       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5026       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5027       if(!cm.isQuadratic())
5028         {
5029           _types.insert(type);
5030           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5031           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5032         }
5033       else
5034         {
5035           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5036           _types.insert(typel);
5037           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5038           int newNbOfNodes=cml.getNumberOfNodes();
5039           if(cml.isDynamic())
5040             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5041           *ocptr++=(int)typel;
5042           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5043           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5044         }
5045     }
5046   setConnectivity(newConn,newConnI,false);
5047 }
5048
5049 /*!
5050  * This method converts all linear cell in \a this to quadratic one.
5051  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5052  * type of cells expected. For example INTERP_KERNEL::NORM_TRI3 can be converted to INTERP_KERNEL::NORM_TRI6 if \a conversionType is equal to 0 (the default)
5053  * or to INTERP_KERNEL::NORM_TRI7 if \a conversionType is equal to 1. All non linear cells and polyhedron in \a this are let untouched.
5054  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5055  * end of the existing coordinates.
5056  * 
5057  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5058  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5059  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5060  * 
5061  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5062  *
5063  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5064  */
5065 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5066 {
5067   DataArrayInt *conn=0,*connI=0;
5068   DataArrayDouble *coords=0;
5069   std::set<INTERP_KERNEL::NormalizedCellType> types;
5070   checkFullyDefined();
5071   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5072   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5073   int meshDim=getMeshDimension();
5074   switch(conversionType)
5075   {
5076     case 0:
5077       switch(meshDim)
5078       {
5079         case 1:
5080           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5081           connSafe=conn; connISafe=connI; coordsSafe=coords;
5082           break;
5083         case 2:
5084           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5085           connSafe=conn; connISafe=connI; coordsSafe=coords;
5086           break;
5087         case 3:
5088           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5089           connSafe=conn; connISafe=connI; coordsSafe=coords;
5090           break;
5091         default:
5092           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5093       }
5094       break;
5095         case 1:
5096           {
5097             switch(meshDim)
5098             {
5099               case 1:
5100                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5101                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5102                 break;
5103               case 2:
5104                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5105                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5106                 break;
5107               case 3:
5108                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5109                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5110                 break;
5111               default:
5112                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5113             }
5114             break;
5115           }
5116         default:
5117           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5118   }
5119   setConnectivity(connSafe,connISafe,false);
5120   _types=types;
5121   setCoords(coordsSafe);
5122   return ret.retn();
5123 }
5124
5125 #if 0
5126 /*!
5127  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5128  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5129  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5130  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5131  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5132  * This method can be seen as the opposite method of colinearize2D.
5133  * This method can be lead to create some new nodes if quadratic polygon cells have to be split. In this case the added nodes will be put at the end
5134  * to avoid to modify the numbering of existing nodes.
5135  *
5136  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5137  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5138  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5139  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5140  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5141  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5142  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5143  *
5144  * \sa buildDescendingConnectivity2
5145  */
5146 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5147                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5148 {
5149   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5150     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5151   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5152   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5153     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5154   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5155     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5156   //DataArrayInt *out0(0),*outi0(0);
5157   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5158   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5159   //out0s=out0s->buildUnique(); out0s->sort(true);
5160 }
5161 #endif
5162
5163 /*!
5164  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5165  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5166  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5167  */
5168 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5169 {
5170   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5171   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5172   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5173   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5174   int nbOfCells=getNumberOfCells();
5175   int nbOfNodes=getNumberOfNodes();
5176   const int *cPtr=_nodal_connec->getConstPointer();
5177   const int *icPtr=_nodal_connec_index->getConstPointer();
5178   int lastVal=0,offset=nbOfNodes;
5179   for(int i=0;i<nbOfCells;i++,icPtr++)
5180     {
5181       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5182       if(type==INTERP_KERNEL::NORM_SEG2)
5183         {
5184           types.insert(INTERP_KERNEL::NORM_SEG3);
5185           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5186           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5187           newConn->pushBackSilent(offset++);
5188           lastVal+=4;
5189           newConnI->pushBackSilent(lastVal);
5190           ret->pushBackSilent(i);
5191         }
5192       else
5193         {
5194           types.insert(type);
5195           lastVal+=(icPtr[1]-icPtr[0]);
5196           newConnI->pushBackSilent(lastVal);
5197           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5198         }
5199     }
5200   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5201   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5202   return ret.retn();
5203 }
5204
5205 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2DAnd3D0(const MEDCouplingUMesh *m1D, const DataArrayInt *desc, const DataArrayInt *descI, DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5206 {
5207   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5208   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5210   //
5211   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5212   DataArrayInt *conn1D=0,*conn1DI=0;
5213   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5214   DataArrayDouble *coordsTmp=0;
5215   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5216   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5217   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5218   const int *c1DPtr=conn1D->begin();
5219   const int *c1DIPtr=conn1DI->begin();
5220   int nbOfCells=getNumberOfCells();
5221   const int *cPtr=_nodal_connec->getConstPointer();
5222   const int *icPtr=_nodal_connec_index->getConstPointer();
5223   int lastVal=0;
5224   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5225     {
5226       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5227       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5228       if(!cm.isQuadratic())
5229         {
5230           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5231           types.insert(typ2); newConn->pushBackSilent(typ2);
5232           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5233           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5234             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5235           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5236           newConnI->pushBackSilent(lastVal);
5237           ret->pushBackSilent(i);
5238         }
5239       else
5240         {
5241           types.insert(typ);
5242           lastVal+=(icPtr[1]-icPtr[0]);
5243           newConnI->pushBackSilent(lastVal);
5244           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5245         }
5246     }
5247   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5248   return ret.retn();
5249 }
5250
5251 /*!
5252  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5253  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5254  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5255  */
5256 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5257 {
5258   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5259   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5260   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5261 }
5262
5263 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5264 {
5265   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5266   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5267   //
5268   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5269   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5270   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5271   //
5272   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5273   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5274   DataArrayInt *conn1D=0,*conn1DI=0;
5275   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5276   DataArrayDouble *coordsTmp=0;
5277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5278   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5280   const int *c1DPtr=conn1D->begin();
5281   const int *c1DIPtr=conn1DI->begin();
5282   int nbOfCells=getNumberOfCells();
5283   const int *cPtr=_nodal_connec->getConstPointer();
5284   const int *icPtr=_nodal_connec_index->getConstPointer();
5285   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5286   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5287     {
5288       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5289       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5290       if(!cm.isQuadratic())
5291         {
5292           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5293           types.insert(typ2); newConn->pushBackSilent(typ2);
5294           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5295           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5296             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5297           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5298           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5299           newConnI->pushBackSilent(lastVal);
5300           ret->pushBackSilent(i);
5301         }
5302       else
5303         {
5304           types.insert(typ);
5305           lastVal+=(icPtr[1]-icPtr[0]);
5306           newConnI->pushBackSilent(lastVal);
5307           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5308         }
5309     }
5310   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5311   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5312   return ret.retn();
5313 }
5314
5315 /*!
5316  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5317  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5318  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5319  */
5320 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5321 {
5322   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5323   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5324   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5325 }
5326
5327 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5328 {
5329   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5330   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5331   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5332   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5333   //
5334   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5337   //
5338   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5339   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5340   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5341   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5342   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5343   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5344   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5345   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5346   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5347   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5348   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5349   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5350   int nbOfCells=getNumberOfCells();
5351   const int *cPtr=_nodal_connec->getConstPointer();
5352   const int *icPtr=_nodal_connec_index->getConstPointer();
5353   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5354   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5355     {
5356       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5357       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5358       if(!cm.isQuadratic())
5359         {
5360           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5361           if(typ2==INTERP_KERNEL::NORM_ERROR)
5362             {
5363               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5364               throw INTERP_KERNEL::Exception(oss.str().c_str());
5365             }
5366           types.insert(typ2); newConn->pushBackSilent(typ2);
5367           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5368           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5369             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5370           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5371             {
5372               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5373               int tmpPos=newConn->getNumberOfTuples();
5374               newConn->pushBackSilent(nodeId2);
5375               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5376             }
5377           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5378           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5379           newConnI->pushBackSilent(lastVal);
5380           ret->pushBackSilent(i);
5381         }
5382       else
5383         {
5384           types.insert(typ);
5385           lastVal+=(icPtr[1]-icPtr[0]);
5386           newConnI->pushBackSilent(lastVal);
5387           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5388         }
5389     }
5390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5392   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5393   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5394   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5395   int *c=newConn->getPointer();
5396   const int *cI(newConnI->begin());
5397   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5398     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5399   offset=coordsTmp2Safe->getNumberOfTuples();
5400   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5401     c[cI[(*elt)+1]-1]+=offset;
5402   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5403   return ret.retn();
5404 }
5405
5406 /*!
5407  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5408  * so that the number of cells remains the same. Quadratic faces are converted to
5409  * polygons. This method works only for 2D meshes in
5410  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5411  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5412  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5413  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5414  *         a polylinized edge constituting the input polygon.
5415  *  \throw If the coordinates array is not set.
5416  *  \throw If the nodal connectivity of cells is not defined.
5417  *  \throw If \a this->getMeshDimension() != 2.
5418  *  \throw If \a this->getSpaceDimension() != 2.
5419  */
5420 void MEDCouplingUMesh::tessellate2D(double eps)
5421 {
5422   checkFullyDefined();
5423   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5424     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5425   double epsa=fabs(eps);
5426   if(epsa<std::numeric_limits<double>::min())
5427     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5428   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5429   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5430   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5432   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5433   revDesc1=0; revDescIndx1=0;
5434   mDesc->tessellate2DCurve(eps);
5435   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5436   setCoords(mDesc->getCoords());
5437 }
5438
5439 /*!
5440  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5441  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5442  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5443  *         a sub-divided edge.
5444  *  \throw If the coordinates array is not set.
5445  *  \throw If the nodal connectivity of cells is not defined.
5446  *  \throw If \a this->getMeshDimension() != 1.
5447  *  \throw If \a this->getSpaceDimension() != 2.
5448  */
5449 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5450 {
5451   checkFullyDefined();
5452   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5453     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5454   double epsa=fabs(eps);
5455   if(epsa<std::numeric_limits<double>::min())
5456     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5457   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5458   int nbCells=getNumberOfCells();
5459   int nbNodes=getNumberOfNodes();
5460   const int *conn=_nodal_connec->getConstPointer();
5461   const int *connI=_nodal_connec_index->getConstPointer();
5462   const double *coords=_coords->getConstPointer();
5463   std::vector<double> addCoo;
5464   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5465   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5466   newConnI->alloc(nbCells+1,1);
5467   int *newConnIPtr=newConnI->getPointer();
5468   *newConnIPtr=0;
5469   int tmp1[3];
5470   INTERP_KERNEL::Node *tmp2[3];
5471   std::set<INTERP_KERNEL::NormalizedCellType> types;
5472   for(int i=0;i<nbCells;i++,newConnIPtr++)
5473     {
5474       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5475       if(cm.isQuadratic())
5476         {//assert(connI[i+1]-connI[i]-1==3)
5477           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5478           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5479           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5480           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5481           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5482           if(eac)
5483             {
5484               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5485               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5486               delete eac;
5487               newConnIPtr[1]=(int)newConn.size();
5488             }
5489           else
5490             {
5491               types.insert(INTERP_KERNEL::NORM_SEG2);
5492               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5493               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5494               newConnIPtr[1]=newConnIPtr[0]+3;
5495             }
5496         }
5497       else
5498         {
5499           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5500           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5501           newConnIPtr[1]=newConnIPtr[0]+3;
5502         }
5503     }
5504   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5505     return ;
5506   _types=types;
5507   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5508   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5509   newConnArr->alloc((int)newConn.size(),1);
5510   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5511   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5512   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5513   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5514   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5515   std::copy(addCoo.begin(),addCoo.end(),work);
5516   DataArrayDouble::SetArrayIn(newCoords,_coords);
5517   updateTime();
5518 }
5519
5520 /*!
5521  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5522  * In addition, returns an array mapping new cells to old ones. <br>
5523  * This method typically increases the number of cells in \a this mesh
5524  * but the number of nodes remains \b unchanged.
5525  * That's why the 3D splitting policies
5526  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5527  *  \param [in] policy - specifies a pattern used for splitting.
5528  * The semantic of \a policy is:
5529  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5530  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5531  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5532  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5533  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5534  *          an id of old cell producing it. The caller is to delete this array using
5535  *         decrRef() as it is no more needed. 
5536  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5537  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5538  *          and \a this->getMeshDimension() != 3. 
5539  *  \throw If \a policy is not one of the four discussed above.
5540  *  \throw If the nodal connectivity of cells is not defined.
5541  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5542  */
5543 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5544 {
5545   switch(policy)
5546   {
5547     case 0:
5548       return simplexizePol0();
5549     case 1:
5550       return simplexizePol1();
5551     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5552         return simplexizePlanarFace5();
5553     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5554         return simplexizePlanarFace6();
5555     default:
5556       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexize : unrecognized policy ! Must be :\n  - 0 or 1 (only available for meshdim=2) \n  - PLANAR_FACE_5, PLANAR_FACE_6  (only for meshdim=3)");
5557   }
5558 }
5559
5560 /*!
5561  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5562  * - 1D: INTERP_KERNEL::NORM_SEG2
5563  * - 2D: INTERP_KERNEL::NORM_TRI3
5564  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5565  *
5566  * This method is useful for users that need to use P1 field services as
5567  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5568  * All these methods need mesh support containing only simplex cells.
5569  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5570  *  \throw If the coordinates array is not set.
5571  *  \throw If the nodal connectivity of cells is not defined.
5572  *  \throw If \a this->getMeshDimension() < 1.
5573  */
5574 bool MEDCouplingUMesh::areOnlySimplexCells() const
5575 {
5576   checkFullyDefined();
5577   int mdim=getMeshDimension();
5578   if(mdim<1 || mdim>3)
5579     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5580   int nbCells=getNumberOfCells();
5581   const int *conn=_nodal_connec->getConstPointer();
5582   const int *connI=_nodal_connec_index->getConstPointer();
5583   for(int i=0;i<nbCells;i++)
5584     {
5585       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5586       if(!cm.isSimplex())
5587         return false;
5588     }
5589   return true;
5590 }
5591
5592 /*!
5593  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5594  */
5595 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5596 {
5597   checkConnectivityFullyDefined();
5598   if(getMeshDimension()!=2)
5599     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5600   int nbOfCells=getNumberOfCells();
5601   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5602   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5603   ret->alloc(nbOfCells+nbOfCutCells,1);
5604   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5605   int *retPt=ret->getPointer();
5606   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5607   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5608   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5609   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5610   int *pt=newConn->getPointer();
5611   int *ptI=newConnI->getPointer();
5612   ptI[0]=0;
5613   const int *oldc=_nodal_connec->getConstPointer();
5614   const int *ci=_nodal_connec_index->getConstPointer();
5615   for(int i=0;i<nbOfCells;i++,ci++)
5616     {
5617       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5618         {
5619           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5620             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5621           pt=std::copy(tmp,tmp+8,pt);
5622           ptI[1]=ptI[0]+4;
5623           ptI[2]=ptI[0]+8;
5624           *retPt++=i;
5625           *retPt++=i;
5626           ptI+=2;
5627         }
5628       else
5629         {
5630           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5631           ptI[1]=ptI[0]+ci[1]-ci[0];
5632           ptI++;
5633           *retPt++=i;
5634         }
5635     }
5636   _nodal_connec->decrRef();
5637   _nodal_connec=newConn.retn();
5638   _nodal_connec_index->decrRef();
5639   _nodal_connec_index=newConnI.retn();
5640   computeTypes();
5641   updateTime();
5642   return ret.retn();
5643 }
5644
5645 /*!
5646  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5647  */
5648 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5649 {
5650   checkConnectivityFullyDefined();
5651   if(getMeshDimension()!=2)
5652     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5653   int nbOfCells=getNumberOfCells();
5654   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5655   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5656   ret->alloc(nbOfCells+nbOfCutCells,1);
5657   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5658   int *retPt=ret->getPointer();
5659   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5660   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5661   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5662   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5663   int *pt=newConn->getPointer();
5664   int *ptI=newConnI->getPointer();
5665   ptI[0]=0;
5666   const int *oldc=_nodal_connec->getConstPointer();
5667   const int *ci=_nodal_connec_index->getConstPointer();
5668   for(int i=0;i<nbOfCells;i++,ci++)
5669     {
5670       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5671         {
5672           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5673             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5674           pt=std::copy(tmp,tmp+8,pt);
5675           ptI[1]=ptI[0]+4;
5676           ptI[2]=ptI[0]+8;
5677           *retPt++=i;
5678           *retPt++=i;
5679           ptI+=2;
5680         }
5681       else
5682         {
5683           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5684           ptI[1]=ptI[0]+ci[1]-ci[0];
5685           ptI++;
5686           *retPt++=i;
5687         }
5688     }
5689   _nodal_connec->decrRef();
5690   _nodal_connec=newConn.retn();
5691   _nodal_connec_index->decrRef();
5692   _nodal_connec_index=newConnI.retn();
5693   computeTypes();
5694   updateTime();
5695   return ret.retn();
5696 }
5697
5698 /*!
5699  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5700  */
5701 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5702 {
5703   checkConnectivityFullyDefined();
5704   if(getMeshDimension()!=3)
5705     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5706   int nbOfCells=getNumberOfCells();
5707   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5708   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5709   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5710   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5711   int *retPt=ret->getPointer();
5712   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5713   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5714   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5715   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5716   int *pt=newConn->getPointer();
5717   int *ptI=newConnI->getPointer();
5718   ptI[0]=0;
5719   const int *oldc=_nodal_connec->getConstPointer();
5720   const int *ci=_nodal_connec_index->getConstPointer();
5721   for(int i=0;i<nbOfCells;i++,ci++)
5722     {
5723       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5724         {
5725           for(int j=0;j<5;j++,pt+=5,ptI++)
5726             {
5727               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5728               pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+3]+1];
5729               *retPt++=i;
5730               ptI[1]=ptI[0]+5;
5731             }
5732         }
5733       else
5734         {
5735           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5736           ptI[1]=ptI[0]+ci[1]-ci[0];
5737           ptI++;
5738           *retPt++=i;
5739         }
5740     }
5741   _nodal_connec->decrRef();
5742   _nodal_connec=newConn.retn();
5743   _nodal_connec_index->decrRef();
5744   _nodal_connec_index=newConnI.retn();
5745   computeTypes();
5746   updateTime();
5747   return ret.retn();
5748 }
5749
5750 /*!
5751  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5752  */
5753 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5754 {
5755   checkConnectivityFullyDefined();
5756   if(getMeshDimension()!=3)
5757     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5758   int nbOfCells=getNumberOfCells();
5759   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5760   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5761   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5762   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5763   int *retPt=ret->getPointer();
5764   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5765   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5766   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5767   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5768   int *pt=newConn->getPointer();
5769   int *ptI=newConnI->getPointer();
5770   ptI[0]=0;
5771   const int *oldc=_nodal_connec->getConstPointer();
5772   const int *ci=_nodal_connec_index->getConstPointer();
5773   for(int i=0;i<nbOfCells;i++,ci++)
5774     {
5775       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5776         {
5777           for(int j=0;j<6;j++,pt+=5,ptI++)
5778             {
5779               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5780               pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+3]+1];
5781               *retPt++=i;
5782               ptI[1]=ptI[0]+5;
5783             }
5784         }
5785       else
5786         {
5787           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5788           ptI[1]=ptI[0]+ci[1]-ci[0];
5789           ptI++;
5790           *retPt++=i;
5791         }
5792     }
5793   _nodal_connec->decrRef();
5794   _nodal_connec=newConn.retn();
5795   _nodal_connec_index->decrRef();
5796   _nodal_connec_index=newConnI.retn();
5797   computeTypes();
5798   updateTime();
5799   return ret.retn();
5800 }
5801
5802 /*!
5803  * This private method is used to subdivide edges of a mesh with meshdim==2. If \a this has no a meshdim equal to 2 an exception will be thrown.
5804  * This method completly ignore coordinates.
5805  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5806  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5807  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5808  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5809  */
5810 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5811 {
5812   checkFullyDefined();
5813   if(getMeshDimension()!=2)
5814     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5815   int nbOfCells=getNumberOfCells();
5816   int *connI=_nodal_connec_index->getPointer();
5817   int newConnLgth=0;
5818   for(int i=0;i<nbOfCells;i++,connI++)
5819     {
5820       int offset=descIndex[i];
5821       int nbOfEdges=descIndex[i+1]-offset;
5822       //
5823       bool ddirect=desc[offset+nbOfEdges-1]>0;
5824       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5825       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5826       for(int j=0;j<nbOfEdges;j++)
5827         {
5828           bool direct=desc[offset+j]>0;
5829           int edgeId=std::abs(desc[offset+j])-1;
5830           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5831             {
5832               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5833               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5834               int ref2=direct?id1:id2;
5835               if(ref==ref2)
5836                 {
5837                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5838                   newConnLgth+=nbOfSubNodes-1;
5839                   ref=direct?id2:id1;
5840                 }
5841               else
5842                 {
5843                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5844                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5845                 }
5846             }
5847           else
5848             {
5849               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5850             }
5851         }
5852       newConnLgth++;//+1 is for cell type
5853       connI[1]=newConnLgth;
5854     }
5855   //
5856   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5857   newConn->alloc(newConnLgth,1);
5858   int *work=newConn->getPointer();
5859   for(int i=0;i<nbOfCells;i++)
5860     {
5861       *work++=INTERP_KERNEL::NORM_POLYGON;
5862       int offset=descIndex[i];
5863       int nbOfEdges=descIndex[i+1]-offset;
5864       for(int j=0;j<nbOfEdges;j++)
5865         {
5866           bool direct=desc[offset+j]>0;
5867           int edgeId=std::abs(desc[offset+j])-1;
5868           if(direct)
5869             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5870           else
5871             {
5872               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5873               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5874               work=std::copy(it,it+nbOfSubNodes-1,work);
5875             }
5876         }
5877     }
5878   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5879   _types.clear();
5880   if(nbOfCells>0)
5881     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5882 }
5883
5884 /*!
5885  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5886  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5887  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5888  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5889  * so it can be useful to call mergeNodes() before calling this method.
5890  *  \throw If \a this->getMeshDimension() <= 1.
5891  *  \throw If the coordinates array is not set.
5892  *  \throw If the nodal connectivity of cells is not defined.
5893  */
5894 void MEDCouplingUMesh::convertDegeneratedCells()
5895 {
5896   checkFullyDefined();
5897   if(getMeshDimension()<=1)
5898     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5899   int nbOfCells=getNumberOfCells();
5900   if(nbOfCells<1)
5901     return ;
5902   int initMeshLgth=getMeshLength();
5903   int *conn=_nodal_connec->getPointer();
5904   int *index=_nodal_connec_index->getPointer();
5905   int posOfCurCell=0;
5906   int newPos=0;
5907   int lgthOfCurCell;
5908   for(int i=0;i<nbOfCells;i++)
5909     {
5910       lgthOfCurCell=index[i+1]-posOfCurCell;
5911       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5912       int newLgth;
5913       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5914                                                                                                      conn+newPos+1,newLgth);
5915       conn[newPos]=newType;
5916       newPos+=newLgth+1;
5917       posOfCurCell=index[i+1];
5918       index[i+1]=newPos;
5919     }
5920   if(newPos!=initMeshLgth)
5921     _nodal_connec->reAlloc(newPos);
5922   computeTypes();
5923 }
5924
5925 /*!
5926  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5927  * A cell is considered to be oriented correctly if an angle between its
5928  * normal vector and a given vector is less than \c PI / \c 2.
5929  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5930  *         cells. 
5931  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5932  *         checked.
5933  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5934  *         is not cleared before filling in.
5935  *  \throw If \a this->getMeshDimension() != 2.
5936  *  \throw If \a this->getSpaceDimension() != 3.
5937  *
5938  *  \if ENABLE_EXAMPLES
5939  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5940  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5941  *  \endif
5942  */
5943 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5944 {
5945   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5946     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5947   int nbOfCells=getNumberOfCells();
5948   const int *conn=_nodal_connec->getConstPointer();
5949   const int *connI=_nodal_connec_index->getConstPointer();
5950   const double *coordsPtr=_coords->getConstPointer();
5951   for(int i=0;i<nbOfCells;i++)
5952     {
5953       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5954       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5955         {
5956           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5957           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5958             cells.push_back(i);
5959         }
5960     }
5961 }
5962
5963 /*!
5964  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5965  * considered to be oriented correctly if an angle between its normal vector and a
5966  * given vector is less than \c PI / \c 2. 
5967  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5968  *         cells. 
5969  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5970  *         checked.
5971  *  \throw If \a this->getMeshDimension() != 2.
5972  *  \throw If \a this->getSpaceDimension() != 3.
5973  *
5974  *  \if ENABLE_EXAMPLES
5975  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5976  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5977  *  \endif
5978  *
5979  *  \sa changeOrientationOfCells
5980  */
5981 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5982 {
5983   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5984     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5985   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
5986   const int *connI(_nodal_connec_index->getConstPointer());
5987   const double *coordsPtr(_coords->getConstPointer());
5988   bool isModified(false);
5989   for(int i=0;i<nbOfCells;i++)
5990     {
5991       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5992       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5993         {
5994           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
5995           bool isQuadratic(cm.isQuadratic());
5996           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5997             {
5998               isModified=true;
5999               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6000             }
6001         }
6002     }
6003   if(isModified)
6004     _nodal_connec->declareAsNew();
6005   updateTime();
6006 }
6007
6008 /*!
6009  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6010  *
6011  * \sa orientCorrectly2DCells
6012  */
6013 void MEDCouplingUMesh::changeOrientationOfCells()
6014 {
6015   int mdim(getMeshDimension());
6016   if(mdim!=2 && mdim!=1)
6017     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6018   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6019   const int *connI(_nodal_connec_index->getConstPointer());
6020   if(mdim==2)
6021     {//2D
6022       for(int i=0;i<nbOfCells;i++)
6023         {
6024           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6025           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6026           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6027         }
6028     }
6029   else
6030     {//1D
6031       for(int i=0;i<nbOfCells;i++)
6032         {
6033           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6034           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6035           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6036         }
6037     }
6038 }
6039
6040 /*!
6041  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6042  * oriented facets. The normal vector of the facet should point out of the cell.
6043  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6044  *         is not cleared before filling in.
6045  *  \throw If \a this->getMeshDimension() != 3.
6046  *  \throw If \a this->getSpaceDimension() != 3.
6047  *  \throw If the coordinates array is not set.
6048  *  \throw If the nodal connectivity of cells is not defined.
6049  *
6050  *  \if ENABLE_EXAMPLES
6051  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6052  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6053  *  \endif
6054  */
6055 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6056 {
6057   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6058     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6059   int nbOfCells=getNumberOfCells();
6060   const int *conn=_nodal_connec->getConstPointer();
6061   const int *connI=_nodal_connec_index->getConstPointer();
6062   const double *coordsPtr=_coords->getConstPointer();
6063   for(int i=0;i<nbOfCells;i++)
6064     {
6065       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6066       if(type==INTERP_KERNEL::NORM_POLYHED)
6067         {
6068           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6069             cells.push_back(i);
6070         }
6071     }
6072 }
6073
6074 /*!
6075  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6076  * out of the cell. 
6077  *  \throw If \a this->getMeshDimension() != 3.
6078  *  \throw If \a this->getSpaceDimension() != 3.
6079  *  \throw If the coordinates array is not set.
6080  *  \throw If the nodal connectivity of cells is not defined.
6081  *  \throw If the reparation fails.
6082  *
6083  *  \if ENABLE_EXAMPLES
6084  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6085  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6086  *  \endif
6087  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6088  */
6089 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6090 {
6091   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6092     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6093   int nbOfCells=getNumberOfCells();
6094   int *conn=_nodal_connec->getPointer();
6095   const int *connI=_nodal_connec_index->getConstPointer();
6096   const double *coordsPtr=_coords->getConstPointer();
6097   for(int i=0;i<nbOfCells;i++)
6098     {
6099       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6100       if(type==INTERP_KERNEL::NORM_POLYHED)
6101         {
6102           try
6103           {
6104               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6105                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6106           }
6107           catch(INTERP_KERNEL::Exception& e)
6108           {
6109               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6110               throw INTERP_KERNEL::Exception(oss.str().c_str());
6111           }
6112         }
6113     }
6114   updateTime();
6115 }
6116
6117 /*!
6118  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6119  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6120  * according to which the first facet of the cell should be oriented to have the normal vector
6121  * pointing out of cell.
6122  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6123  *         cells. The caller is to delete this array using decrRef() as it is no more
6124  *         needed. 
6125  *  \throw If \a this->getMeshDimension() != 3.
6126  *  \throw If \a this->getSpaceDimension() != 3.
6127  *  \throw If the coordinates array is not set.
6128  *  \throw If the nodal connectivity of cells is not defined.
6129  *
6130  *  \if ENABLE_EXAMPLES
6131  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6132  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6133  *  \endif
6134  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6135  */
6136 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6137 {
6138   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6139   if(getMeshDimension()!=3)
6140     throw INTERP_KERNEL::Exception(msg);
6141   int spaceDim=getSpaceDimension();
6142   if(spaceDim!=3)
6143     throw INTERP_KERNEL::Exception(msg);
6144   //
6145   int nbOfCells=getNumberOfCells();
6146   int *conn=_nodal_connec->getPointer();
6147   const int *connI=_nodal_connec_index->getConstPointer();
6148   const double *coo=getCoords()->getConstPointer();
6149   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6150   for(int i=0;i<nbOfCells;i++)
6151     {
6152       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6153       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6154         {
6155           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6156             {
6157               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6158               cells->pushBackSilent(i);
6159             }
6160         }
6161     }
6162   return cells.retn();
6163 }
6164
6165 /*!
6166  * This method is a faster method to correct orientation of all 3D cells in \a this.
6167  * This method works only if \a this is a 3D mesh, that is to say a mesh with mesh dimension 3 and a space dimension 3.
6168  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6169  * 
6170  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6171  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6172  */
6173 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6174 {
6175   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6176     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6177   int nbOfCells=getNumberOfCells();
6178   int *conn=_nodal_connec->getPointer();
6179   const int *connI=_nodal_connec_index->getConstPointer();
6180   const double *coordsPtr=_coords->getConstPointer();
6181   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6182   for(int i=0;i<nbOfCells;i++)
6183     {
6184       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6185       switch(type)
6186       {
6187         case INTERP_KERNEL::NORM_TETRA4:
6188           {
6189             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6190               {
6191                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6192                 ret->pushBackSilent(i);
6193               }
6194             break;
6195           }
6196         case INTERP_KERNEL::NORM_PYRA5:
6197           {
6198             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6199               {
6200                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6201                 ret->pushBackSilent(i);
6202               }
6203             break;
6204           }
6205         case INTERP_KERNEL::NORM_PENTA6:
6206         case INTERP_KERNEL::NORM_HEXA8:
6207         case INTERP_KERNEL::NORM_HEXGP12:
6208           {
6209             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6210               {
6211                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6212                 ret->pushBackSilent(i);
6213               }
6214             break;
6215           }
6216         case INTERP_KERNEL::NORM_POLYHED:
6217           {
6218             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6219               {
6220                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6221                 ret->pushBackSilent(i);
6222               }
6223             break;
6224           }
6225         default:
6226           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orientCorrectly3DCells : Your mesh contains type of cell not supported yet ! send mail to anthony.geay@cea.fr to add it !");
6227       }
6228     }
6229   updateTime();
6230   return ret.retn();
6231 }
6232
6233 /*!
6234  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6235  * If it is not the case an exception will be thrown.
6236  * This method is fast because the first cell of \a this is used to compute the plane.
6237  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6238  * \param pos output of size at least 3 used to store a point owned of searched plane.
6239  */
6240 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6241 {
6242   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6243     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6244   const int *conn=_nodal_connec->getConstPointer();
6245   const int *connI=_nodal_connec_index->getConstPointer();
6246   const double *coordsPtr=_coords->getConstPointer();
6247   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6248   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6249 }
6250
6251 /*!
6252  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6253  * cells. Currently cells of the following types are treated:
6254  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6255  * For a cell of other type an exception is thrown.
6256  * Space dimension of a 2D mesh can be either 2 or 3.
6257  * The Edge Ratio of a cell \f$t\f$ is: 
6258  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6259  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6260  *  the smallest edge lengths of \f$t\f$.
6261  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6262  *          cells and one time, lying on \a this mesh. The caller is to delete this
6263  *          field using decrRef() as it is no more needed. 
6264  *  \throw If the coordinates array is not set.
6265  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6266  *  \throw If the connectivity data array has more than one component.
6267  *  \throw If the connectivity data array has a named component.
6268  *  \throw If the connectivity index data array has more than one component.
6269  *  \throw If the connectivity index data array has a named component.
6270  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6271  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6272  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6273  */
6274 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6275 {
6276   checkCoherency();
6277   int spaceDim=getSpaceDimension();
6278   int meshDim=getMeshDimension();
6279   if(spaceDim!=2 && spaceDim!=3)
6280     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6281   if(meshDim!=2 && meshDim!=3)
6282     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6283   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6284   ret->setMesh(this);
6285   int nbOfCells=getNumberOfCells();
6286   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6287   arr->alloc(nbOfCells,1);
6288   double *pt=arr->getPointer();
6289   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6290   const int *conn=_nodal_connec->getConstPointer();
6291   const int *connI=_nodal_connec_index->getConstPointer();
6292   const double *coo=_coords->getConstPointer();
6293   double tmp[12];
6294   for(int i=0;i<nbOfCells;i++,pt++)
6295     {
6296       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6297       switch(t)
6298       {
6299         case INTERP_KERNEL::NORM_TRI3:
6300           {
6301             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6302             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6303             break;
6304           }
6305         case INTERP_KERNEL::NORM_QUAD4:
6306           {
6307             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6308             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6309             break;
6310           }
6311         case INTERP_KERNEL::NORM_TETRA4:
6312           {
6313             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6314             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6315             break;
6316           }
6317         default:
6318           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6319       }
6320       conn+=connI[i+1]-connI[i];
6321     }
6322   ret->setName("EdgeRatio");
6323   ret->synchronizeTimeWithSupport();
6324   return ret.retn();
6325 }
6326
6327 /*!
6328  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6329  * cells. Currently cells of the following types are treated:
6330  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6331  * For a cell of other type an exception is thrown.
6332  * Space dimension of a 2D mesh can be either 2 or 3.
6333  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6334  *          cells and one time, lying on \a this mesh. The caller is to delete this
6335  *          field using decrRef() as it is no more needed. 
6336  *  \throw If the coordinates array is not set.
6337  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6338  *  \throw If the connectivity data array has more than one component.
6339  *  \throw If the connectivity data array has a named component.
6340  *  \throw If the connectivity index data array has more than one component.
6341  *  \throw If the connectivity index data array has a named component.
6342  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6343  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6344  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6345  */
6346 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6347 {
6348   checkCoherency();
6349   int spaceDim=getSpaceDimension();
6350   int meshDim=getMeshDimension();
6351   if(spaceDim!=2 && spaceDim!=3)
6352     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6353   if(meshDim!=2 && meshDim!=3)
6354     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6355   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6356   ret->setMesh(this);
6357   int nbOfCells=getNumberOfCells();
6358   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6359   arr->alloc(nbOfCells,1);
6360   double *pt=arr->getPointer();
6361   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6362   const int *conn=_nodal_connec->getConstPointer();
6363   const int *connI=_nodal_connec_index->getConstPointer();
6364   const double *coo=_coords->getConstPointer();
6365   double tmp[12];
6366   for(int i=0;i<nbOfCells;i++,pt++)
6367     {
6368       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6369       switch(t)
6370       {
6371         case INTERP_KERNEL::NORM_TRI3:
6372           {
6373             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6374             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6375             break;
6376           }
6377         case INTERP_KERNEL::NORM_QUAD4:
6378           {
6379             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6380             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6381             break;
6382           }
6383         case INTERP_KERNEL::NORM_TETRA4:
6384           {
6385             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6386             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6387             break;
6388           }
6389         default:
6390           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6391       }
6392       conn+=connI[i+1]-connI[i];
6393     }
6394   ret->setName("AspectRatio");
6395   ret->synchronizeTimeWithSupport();
6396   return ret.retn();
6397 }
6398
6399 /*!
6400  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6401  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6402  * treated: INTERP_KERNEL::NORM_QUAD4.
6403  * For a cell of other type an exception is thrown.
6404  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6405  *          cells and one time, lying on \a this mesh. The caller is to delete this
6406  *          field using decrRef() as it is no more needed. 
6407  *  \throw If the coordinates array is not set.
6408  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6409  *  \throw If the connectivity data array has more than one component.
6410  *  \throw If the connectivity data array has a named component.
6411  *  \throw If the connectivity index data array has more than one component.
6412  *  \throw If the connectivity index data array has a named component.
6413  *  \throw If \a this->getMeshDimension() != 2.
6414  *  \throw If \a this->getSpaceDimension() != 3.
6415  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6416  */
6417 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6418 {
6419   checkCoherency();
6420   int spaceDim=getSpaceDimension();
6421   int meshDim=getMeshDimension();
6422   if(spaceDim!=3)
6423     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6424   if(meshDim!=2)
6425     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6426   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6427   ret->setMesh(this);
6428   int nbOfCells=getNumberOfCells();
6429   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6430   arr->alloc(nbOfCells,1);
6431   double *pt=arr->getPointer();
6432   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6433   const int *conn=_nodal_connec->getConstPointer();
6434   const int *connI=_nodal_connec_index->getConstPointer();
6435   const double *coo=_coords->getConstPointer();
6436   double tmp[12];
6437   for(int i=0;i<nbOfCells;i++,pt++)
6438     {
6439       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6440       switch(t)
6441       {
6442         case INTERP_KERNEL::NORM_QUAD4:
6443           {
6444             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6445             *pt=INTERP_KERNEL::quadWarp(tmp);
6446             break;
6447           }
6448         default:
6449           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6450       }
6451       conn+=connI[i+1]-connI[i];
6452     }
6453   ret->setName("Warp");
6454   ret->synchronizeTimeWithSupport();
6455   return ret.retn();
6456 }
6457
6458
6459 /*!
6460  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6461  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6462  * treated: INTERP_KERNEL::NORM_QUAD4.
6463  * For a cell of other type an exception is thrown.
6464  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6465  *          cells and one time, lying on \a this mesh. The caller is to delete this
6466  *          field using decrRef() as it is no more needed. 
6467  *  \throw If the coordinates array is not set.
6468  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6469  *  \throw If the connectivity data array has more than one component.
6470  *  \throw If the connectivity data array has a named component.
6471  *  \throw If the connectivity index data array has more than one component.
6472  *  \throw If the connectivity index data array has a named component.
6473  *  \throw If \a this->getMeshDimension() != 2.
6474  *  \throw If \a this->getSpaceDimension() != 3.
6475  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6476  */
6477 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6478 {
6479   checkCoherency();
6480   int spaceDim=getSpaceDimension();
6481   int meshDim=getMeshDimension();
6482   if(spaceDim!=3)
6483     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6484   if(meshDim!=2)
6485     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6486   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6487   ret->setMesh(this);
6488   int nbOfCells=getNumberOfCells();
6489   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6490   arr->alloc(nbOfCells,1);
6491   double *pt=arr->getPointer();
6492   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6493   const int *conn=_nodal_connec->getConstPointer();
6494   const int *connI=_nodal_connec_index->getConstPointer();
6495   const double *coo=_coords->getConstPointer();
6496   double tmp[12];
6497   for(int i=0;i<nbOfCells;i++,pt++)
6498     {
6499       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6500       switch(t)
6501       {
6502         case INTERP_KERNEL::NORM_QUAD4:
6503           {
6504             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6505             *pt=INTERP_KERNEL::quadSkew(tmp);
6506             break;
6507           }
6508         default:
6509           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6510       }
6511       conn+=connI[i+1]-connI[i];
6512     }
6513   ret->setName("Skew");
6514   ret->synchronizeTimeWithSupport();
6515   return ret.retn();
6516 }
6517
6518 /*!
6519  * 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.
6520  *
6521  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6522  *
6523  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6524  */
6525 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6526 {
6527   checkCoherency();
6528   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6529   ret->setMesh(this);
6530   std::set<INTERP_KERNEL::NormalizedCellType> types;
6531   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6532   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6533   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6534   arr->alloc(nbCells,1);
6535   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6536     {
6537       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6538       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6539       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6540     }
6541   ret->setArray(arr);
6542   ret->setName("Diameter");
6543   return ret.retn();
6544 }
6545
6546 /*!
6547  * This method aggregate the bbox of each cell and put it into bbox parameter.
6548  * 
6549  * \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)
6550  *                         For all other cases this input parameter is ignored.
6551  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6552  * 
6553  * \throw If \a this is not fully set (coordinates and connectivity).
6554  * \throw If a cell in \a this has no valid nodeId.
6555  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6556  */
6557 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6558 {
6559   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6560   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.
6561     return getBoundingBoxForBBTreeFast();
6562   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6563     {
6564       bool presenceOfQuadratic(false);
6565       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6566         {
6567           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6568           if(cm.isQuadratic())
6569             presenceOfQuadratic=true;
6570         }
6571       if(!presenceOfQuadratic)
6572         return getBoundingBoxForBBTreeFast();
6573       if(mDim==2 && sDim==2)
6574         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6575       else
6576         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6577     }
6578   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) !");
6579 }
6580
6581 /*!
6582  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6583  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6584  * 
6585  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6586  * 
6587  * \throw If \a this is not fully set (coordinates and connectivity).
6588  * \throw If a cell in \a this has no valid nodeId.
6589  */
6590 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6591 {
6592   checkFullyDefined();
6593   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6594   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6595   double *bbox(ret->getPointer());
6596   for(int i=0;i<nbOfCells*spaceDim;i++)
6597     {
6598       bbox[2*i]=std::numeric_limits<double>::max();
6599       bbox[2*i+1]=-std::numeric_limits<double>::max();
6600     }
6601   const double *coordsPtr(_coords->getConstPointer());
6602   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6603   for(int i=0;i<nbOfCells;i++)
6604     {
6605       int offset=connI[i]+1;
6606       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6607       for(int j=0;j<nbOfNodesForCell;j++)
6608         {
6609           int nodeId=conn[offset+j];
6610           if(nodeId>=0 && nodeId<nbOfNodes)
6611             {
6612               for(int k=0;k<spaceDim;k++)
6613                 {
6614                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6615                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6616                 }
6617               kk++;
6618             }
6619         }
6620       if(kk==0)
6621         {
6622           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6623           throw INTERP_KERNEL::Exception(oss.str().c_str());
6624         }
6625     }
6626   return ret.retn();
6627 }
6628
6629 /*!
6630  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6631  * useful for 2D meshes having quadratic cells
6632  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6633  * the two extremities of the arc of circle).
6634  * 
6635  * \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)
6636  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6637  * \throw If \a this is not fully defined.
6638  * \throw If \a this is not a mesh with meshDimension equal to 2.
6639  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6640  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6641  */
6642 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6643 {
6644   checkFullyDefined();
6645   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6646   if(spaceDim!=2 || mDim!=2)
6647     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!");
6648   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6649   double *bbox(ret->getPointer());
6650   const double *coords(_coords->getConstPointer());
6651   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6652   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6653     {
6654       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6655       int sz(connI[1]-connI[0]-1);
6656       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6657       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6658       INTERP_KERNEL::QuadraticPolygon *pol(0);
6659       for(int j=0;j<sz;j++)
6660         {
6661           int nodeId(conn[*connI+1+j]);
6662           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6663         }
6664       if(!cm.isQuadratic())
6665         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6666       else
6667         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6668       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6669       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6670     }
6671   return ret.retn();
6672 }
6673
6674 /*!
6675  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6676  * useful for 2D meshes having quadratic cells
6677  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6678  * the two extremities of the arc of circle).
6679  * 
6680  * \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)
6681  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6682  * \throw If \a this is not fully defined.
6683  * \throw If \a this is not a mesh with meshDimension equal to 1.
6684  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6685  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6686  */
6687 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6688 {
6689   checkFullyDefined();
6690   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6691   if(spaceDim!=2 || mDim!=1)
6692     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!");
6693   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6694   double *bbox(ret->getPointer());
6695   const double *coords(_coords->getConstPointer());
6696   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6697   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6698     {
6699       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6700       int sz(connI[1]-connI[0]-1);
6701       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6702       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6703       INTERP_KERNEL::Edge *edge(0);
6704       for(int j=0;j<sz;j++)
6705         {
6706           int nodeId(conn[*connI+1+j]);
6707           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6708         }
6709       if(!cm.isQuadratic())
6710         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6711       else
6712         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6713       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6714       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6715     }
6716   return ret.retn();
6717 }
6718
6719 /// @cond INTERNAL
6720
6721 namespace ParaMEDMEMImpl
6722 {
6723   class ConnReader
6724   {
6725   public:
6726     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6727     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6728   private:
6729     const int *_conn;
6730     int _val;
6731   };
6732
6733   class ConnReader2
6734   {
6735   public:
6736     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6737     bool operator() (const int& pos) { return _conn[pos]==_val; }
6738   private:
6739     const int *_conn;
6740     int _val;
6741   };
6742 }
6743
6744 /// @endcond
6745
6746 /*!
6747  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6748  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6749  * \a this is composed in cell types.
6750  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6751  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6752  * This parameter is kept only for compatibility with other methode listed above.
6753  */
6754 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6755 {
6756   checkConnectivityFullyDefined();
6757   const int *conn=_nodal_connec->getConstPointer();
6758   const int *connI=_nodal_connec_index->getConstPointer();
6759   const int *work=connI;
6760   int nbOfCells=getNumberOfCells();
6761   std::size_t n=getAllGeoTypes().size();
6762   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6763   std::set<INTERP_KERNEL::NormalizedCellType> types;
6764   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6765     {
6766       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6767       if(types.find(typ)!=types.end())
6768         {
6769           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6770           oss << " is not contiguous !";
6771           throw INTERP_KERNEL::Exception(oss.str().c_str());
6772         }
6773       types.insert(typ);
6774       ret[3*i]=typ;
6775       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6776       ret[3*i+1]=(int)std::distance(work,work2);
6777       work=work2;
6778     }
6779   return ret;
6780 }
6781
6782 /*!
6783  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6784  * only for types cell, type node is not managed.
6785  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6786  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6787  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6788  * If 2 or more same geometric type is in \a code and exception is thrown too.
6789  *
6790  * This method firstly checks
6791  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6792  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6793  * an exception is thrown too.
6794  * 
6795  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6796  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6797  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6798  */
6799 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6800 {
6801   if(code.empty())
6802     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6803   std::size_t sz=code.size();
6804   std::size_t n=sz/3;
6805   if(sz%3!=0)
6806     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6807   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6808   int nb=0;
6809   bool isNoPflUsed=true;
6810   for(std::size_t i=0;i<n;i++)
6811     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6812       {
6813         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6814         nb+=code[3*i+1];
6815         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6816           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6817         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6818       }
6819   if(types.size()!=n)
6820     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6821   if(isNoPflUsed)
6822     {
6823       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6824         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6825       if(types.size()==_types.size())
6826         return 0;
6827     }
6828   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6829   ret->alloc(nb,1);
6830   int *retPtr=ret->getPointer();
6831   const int *connI=_nodal_connec_index->getConstPointer();
6832   const int *conn=_nodal_connec->getConstPointer();
6833   int nbOfCells=getNumberOfCells();
6834   const int *i=connI;
6835   int kk=0;
6836   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6837     {
6838       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6839       int offset=(int)std::distance(connI,i);
6840       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6841       int nbOfCellsOfCurType=(int)std::distance(i,j);
6842       if(code[3*kk+2]==-1)
6843         for(int k=0;k<nbOfCellsOfCurType;k++)
6844           *retPtr++=k+offset;
6845       else
6846         {
6847           int idInIdsPerType=code[3*kk+2];
6848           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6849             {
6850               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6851               if(zePfl)
6852                 {
6853                   zePfl->checkAllocated();
6854                   if(zePfl->getNumberOfComponents()==1)
6855                     {
6856                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6857                         {
6858                           if(*k>=0 && *k<nbOfCellsOfCurType)
6859                             *retPtr=(*k)+offset;
6860                           else
6861                             {
6862                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6863                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6864                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6865                             }
6866                         }
6867                     }
6868                   else
6869                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6870                 }
6871               else
6872                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6873             }
6874           else
6875             {
6876               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6877               oss << " should be in [0," << idsPerType.size() << ") !";
6878               throw INTERP_KERNEL::Exception(oss.str().c_str());
6879             }
6880         }
6881       i=j;
6882     }
6883   return ret.retn();
6884 }
6885
6886 /*!
6887  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6888  * 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.
6889  * 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.
6890  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6891  * 
6892  * \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.
6893  * \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,
6894  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6895  * \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.
6896  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6897  * \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
6898  */
6899 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6900 {
6901   if(!profile)
6902     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6903   if(profile->getNumberOfComponents()!=1)
6904     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6905   checkConnectivityFullyDefined();
6906   const int *conn=_nodal_connec->getConstPointer();
6907   const int *connI=_nodal_connec_index->getConstPointer();
6908   int nbOfCells=getNumberOfCells();
6909   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6910   std::vector<int> typeRangeVals(1);
6911   for(const int *i=connI;i!=connI+nbOfCells;)
6912     {
6913       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6914       if(std::find(types.begin(),types.end(),curType)!=types.end())
6915         {
6916           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6917         }
6918       types.push_back(curType);
6919       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6920       typeRangeVals.push_back((int)std::distance(connI,i));
6921     }
6922   //
6923   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6924   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6925   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6926   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6927   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6928   //
6929   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6930   code.resize(3*nbOfCastsFinal);
6931   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6932   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6933   for(int i=0;i<nbOfCastsFinal;i++)
6934     {
6935       int castId=castsPresent->getIJ(i,0);
6936       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6937       idsInPflPerType2.push_back(tmp3);
6938       code[3*i]=(int)types[castId];
6939       code[3*i+1]=tmp3->getNumberOfTuples();
6940       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6941       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6942         {
6943           tmp4->copyStringInfoFrom(*profile);
6944           idsPerType2.push_back(tmp4);
6945           code[3*i+2]=(int)idsPerType2.size()-1;
6946         }
6947       else
6948         {
6949           code[3*i+2]=-1;
6950         }
6951     }
6952   std::size_t sz2=idsInPflPerType2.size();
6953   idsInPflPerType.resize(sz2);
6954   for(std::size_t i=0;i<sz2;i++)
6955     {
6956       DataArrayInt *locDa=idsInPflPerType2[i];
6957       locDa->incrRef();
6958       idsInPflPerType[i]=locDa;
6959     }
6960   std::size_t sz=idsPerType2.size();
6961   idsPerType.resize(sz);
6962   for(std::size_t i=0;i<sz;i++)
6963     {
6964       DataArrayInt *locDa=idsPerType2[i];
6965       locDa->incrRef();
6966       idsPerType[i]=locDa;
6967     }
6968 }
6969
6970 /*!
6971  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6972  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6973  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6974  * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as ParaMEDMEM::MEDCouplingUMesh::buildDescendingConnectivity except the content as described after. The returned array specifies the n-1 mesh reordered by type as MEDMEM does. 'nM1LevMeshIds' contains the ids in returned 'meshnM1'. Finally 'meshnM1Old2New' contains numbering old2new that is to say the cell #k in coarse 'nM1LevMesh' will have the number ret[k] in returned mesh 'nM1LevMesh' MEDMEM reordered.
6975  */
6976 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6977 {
6978   checkFullyDefined();
6979   nM1LevMesh->checkFullyDefined();
6980   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6981     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6982   if(_coords!=nM1LevMesh->getCoords())
6983     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6984   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6985   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6986   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6987   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6988   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6989   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6990   tmp->setConnectivity(tmp0,tmp1);
6991   tmp->renumberCells(ret0->getConstPointer(),false);
6992   revDesc=tmp->getNodalConnectivity();
6993   revDescIndx=tmp->getNodalConnectivityIndex();
6994   DataArrayInt *ret=0;
6995   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6996     {
6997       int tmp2;
6998       ret->getMaxValue(tmp2);
6999       ret->decrRef();
7000       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7001       throw INTERP_KERNEL::Exception(oss.str().c_str());
7002     }
7003   nM1LevMeshIds=ret;
7004   //
7005   revDesc->incrRef();
7006   revDescIndx->incrRef();
7007   ret1->incrRef();
7008   ret0->incrRef();
7009   meshnM1Old2New=ret0;
7010   return ret1;
7011 }
7012
7013 /*!
7014  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7015  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7016  * in "Old to New" mode.
7017  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7018  *          this array using decrRef() as it is no more needed.
7019  *  \throw If the nodal connectivity of cells is not defined.
7020  */
7021 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7022 {
7023   checkConnectivityFullyDefined();
7024   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7025   renumberCells(ret->getConstPointer(),false);
7026   return ret.retn();
7027 }
7028
7029 /*!
7030  * This methods checks that cells are sorted by their types.
7031  * This method makes asumption (no check) that connectivity is correctly set before calling.
7032  */
7033 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7034 {
7035   checkFullyDefined();
7036   const int *conn=_nodal_connec->getConstPointer();
7037   const int *connI=_nodal_connec_index->getConstPointer();
7038   int nbOfCells=getNumberOfCells();
7039   std::set<INTERP_KERNEL::NormalizedCellType> types;
7040   for(const int *i=connI;i!=connI+nbOfCells;)
7041     {
7042       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7043       if(types.find(curType)!=types.end())
7044         return false;
7045       types.insert(curType);
7046       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7047     }
7048   return true;
7049 }
7050
7051 /*!
7052  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7053  * The geometric type order is specified by MED file.
7054  * 
7055  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7056  */
7057 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7058 {
7059   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7060 }
7061
7062 /*!
7063  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7064  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7065  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7066  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7067  */
7068 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7069 {
7070   checkFullyDefined();
7071   const int *conn=_nodal_connec->getConstPointer();
7072   const int *connI=_nodal_connec_index->getConstPointer();
7073   int nbOfCells=getNumberOfCells();
7074   if(nbOfCells==0)
7075     return true;
7076   int lastPos=-1;
7077   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7078   for(const int *i=connI;i!=connI+nbOfCells;)
7079     {
7080       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7081       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7082       if(isTypeExists!=orderEnd)
7083         {
7084           int pos=(int)std::distance(orderBg,isTypeExists);
7085           if(pos<=lastPos)
7086             return false;
7087           lastPos=pos;
7088           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7089         }
7090       else
7091         {
7092           if(sg.find(curType)==sg.end())
7093             {
7094               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7095               sg.insert(curType);
7096             }
7097           else
7098             return false;
7099         }
7100     }
7101   return true;
7102 }
7103
7104 /*!
7105  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7106  * 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
7107  * 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'.
7108  */
7109 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7110 {
7111   checkConnectivityFullyDefined();
7112   int nbOfCells=getNumberOfCells();
7113   const int *conn=_nodal_connec->getConstPointer();
7114   const int *connI=_nodal_connec_index->getConstPointer();
7115   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7116   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7117   tmpa->alloc(nbOfCells,1);
7118   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7119   tmpb->fillWithZero();
7120   int *tmp=tmpa->getPointer();
7121   int *tmp2=tmpb->getPointer();
7122   for(const int *i=connI;i!=connI+nbOfCells;i++)
7123     {
7124       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7125       if(where!=orderEnd)
7126         {
7127           int pos=(int)std::distance(orderBg,where);
7128           tmp2[pos]++;
7129           tmp[std::distance(connI,i)]=pos;
7130         }
7131       else
7132         {
7133           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7134           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7135           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7136           throw INTERP_KERNEL::Exception(oss.str().c_str());
7137         }
7138     }
7139   nbPerType=tmpb.retn();
7140   return tmpa.retn();
7141 }
7142
7143 /*!
7144  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7145  *
7146  * \return a new object containing the old to new correspondance.
7147  *
7148  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7149  */
7150 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7151 {
7152   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7153 }
7154
7155 /*!
7156  * 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.
7157  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7158  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7159  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7160  */
7161 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7162 {
7163   DataArrayInt *nbPerType=0;
7164   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7165   nbPerType->decrRef();
7166   return tmpa->buildPermArrPerLevel();
7167 }
7168
7169 /*!
7170  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7171  * The number of cells remains unchanged after the call of this method.
7172  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7173  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7174  *
7175  * \return the array giving the correspondance old to new.
7176  */
7177 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7178 {
7179   checkFullyDefined();
7180   computeTypes();
7181   const int *conn=_nodal_connec->getConstPointer();
7182   const int *connI=_nodal_connec_index->getConstPointer();
7183   int nbOfCells=getNumberOfCells();
7184   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7185   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7186     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7187       {
7188         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7189         types.push_back(curType);
7190         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7191       }
7192   DataArrayInt *ret=DataArrayInt::New();
7193   ret->alloc(nbOfCells,1);
7194   int *retPtr=ret->getPointer();
7195   std::fill(retPtr,retPtr+nbOfCells,-1);
7196   int newCellId=0;
7197   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7198     {
7199       for(const int *i=connI;i!=connI+nbOfCells;i++)
7200         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7201           retPtr[std::distance(connI,i)]=newCellId++;
7202     }
7203   renumberCells(retPtr,false);
7204   return ret;
7205 }
7206
7207 /*!
7208  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7209  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7210  * This method makes asumption that connectivity is correctly set before calling.
7211  */
7212 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7213 {
7214   checkConnectivityFullyDefined();
7215   const int *conn=_nodal_connec->getConstPointer();
7216   const int *connI=_nodal_connec_index->getConstPointer();
7217   int nbOfCells=getNumberOfCells();
7218   std::vector<MEDCouplingUMesh *> ret;
7219   for(const int *i=connI;i!=connI+nbOfCells;)
7220     {
7221       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7222       int beginCellId=(int)std::distance(connI,i);
7223       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7224       int endCellId=(int)std::distance(connI,i);
7225       int sz=endCellId-beginCellId;
7226       int *cells=new int[sz];
7227       for(int j=0;j<sz;j++)
7228         cells[j]=beginCellId+j;
7229       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7230       delete [] cells;
7231       ret.push_back(m);
7232     }
7233   return ret;
7234 }
7235
7236 /*!
7237  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7238  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7239  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7240  *
7241  * \return a newly allocated instance, that the caller must manage.
7242  * \throw If \a this contains more than one geometric type.
7243  * \throw If the nodal connectivity of \a this is not fully defined.
7244  * \throw If the internal data is not coherent.
7245  */
7246 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7247 {
7248   checkConnectivityFullyDefined();
7249   if(_types.size()!=1)
7250     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7251   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7252   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7253   ret->setCoords(getCoords());
7254   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7255   if(retC)
7256     {
7257       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7258       retC->setNodalConnectivity(c);
7259     }
7260   else
7261     {
7262       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7263       if(!retD)
7264         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7265       DataArrayInt *c=0,*ci=0;
7266       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7267       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7268       retD->setNodalConnectivity(cs,cis);
7269     }
7270   return ret.retn();
7271 }
7272
7273 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7274 {
7275   checkConnectivityFullyDefined();
7276   if(_types.size()!=1)
7277     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7278   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7279   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7280   if(cm.isDynamic())
7281     {
7282       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7283       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7284       throw INTERP_KERNEL::Exception(oss.str().c_str());
7285     }
7286   int nbCells=getNumberOfCells();
7287   int typi=(int)typ;
7288   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7289   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7290   int *outPtr=connOut->getPointer();
7291   const int *conn=_nodal_connec->begin();
7292   const int *connI=_nodal_connec_index->begin();
7293   nbNodesPerCell++;
7294   for(int i=0;i<nbCells;i++,connI++)
7295     {
7296       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7297         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7298       else
7299         {
7300           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 << ") !";
7301           throw INTERP_KERNEL::Exception(oss.str().c_str());
7302         }
7303     }
7304   return connOut.retn();
7305 }
7306
7307 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7308 {
7309   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7310   checkConnectivityFullyDefined();
7311   if(_types.size()!=1)
7312     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7313   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7314   if(lgth<nbCells)
7315     throw INTERP_KERNEL::Exception(msg0);
7316   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7317   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7318   int *cp(c->getPointer()),*cip(ci->getPointer());
7319   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7320   cip[0]=0;
7321   for(int i=0;i<nbCells;i++,cip++,incip++)
7322     {
7323       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7324       int delta(stop-strt);
7325       if(delta>=1)
7326         {
7327           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7328             cp=std::copy(incp+strt,incp+stop,cp);
7329           else
7330             throw INTERP_KERNEL::Exception(msg0);
7331         }
7332       else
7333         throw INTERP_KERNEL::Exception(msg0);
7334       cip[1]=cip[0]+delta;
7335     }
7336   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7337 }
7338
7339 /*!
7340  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7341  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7342  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7343  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7344  * are not used here to avoid the build of big permutation array.
7345  *
7346  * \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
7347  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7348  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7349  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7350  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7351  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7352  * \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
7353  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7354  */
7355 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7356                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7357                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7358 {
7359   std::vector<const MEDCouplingUMesh *> ms2;
7360   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7361     if(*it)
7362       {
7363         (*it)->checkConnectivityFullyDefined();
7364         ms2.push_back(*it);
7365       }
7366   if(ms2.empty())
7367     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7368   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7369   int meshDim=ms2[0]->getMeshDimension();
7370   std::vector<const MEDCouplingUMesh *> m1ssm;
7371   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7372   //
7373   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7374   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7375   int fake=0,rk=0;
7376   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7377   ret1->alloc(0,1); ret2->alloc(0,1);
7378   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7379     {
7380       if(meshDim!=(*it)->getMeshDimension())
7381         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7382       if(refCoo!=(*it)->getCoords())
7383         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7384       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7385       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7386       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7387       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7388         {
7389           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7390           m1ssmSingleAuto.push_back(singleCell);
7391           m1ssmSingle.push_back(singleCell);
7392           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7393         }
7394     }
7395   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7397   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7398   for(std::size_t i=0;i<m1ssm.size();i++)
7399     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7400   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7401   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7402   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7403   return ret0.retn();
7404 }
7405
7406 /*!
7407  * This method returns a newly created DataArrayInt instance.
7408  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7409  */
7410 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7411 {
7412   checkFullyDefined();
7413   const int *conn=_nodal_connec->getConstPointer();
7414   const int *connIndex=_nodal_connec_index->getConstPointer();
7415   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7416   for(const int *w=begin;w!=end;w++)
7417     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7418       ret->pushBackSilent(*w);
7419   return ret.retn();
7420 }
7421
7422 /*!
7423  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7424  * are in [0:getNumberOfCells())
7425  */
7426 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7427 {
7428   checkFullyDefined();
7429   const int *conn=_nodal_connec->getConstPointer();
7430   const int *connI=_nodal_connec_index->getConstPointer();
7431   int nbOfCells=getNumberOfCells();
7432   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7433   int *tmp=new int[nbOfCells];
7434   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7435     {
7436       int j=0;
7437       for(const int *i=connI;i!=connI+nbOfCells;i++)
7438         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7439           tmp[std::distance(connI,i)]=j++;
7440     }
7441   DataArrayInt *ret=DataArrayInt::New();
7442   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7443   ret->copyStringInfoFrom(*da);
7444   int *retPtr=ret->getPointer();
7445   const int *daPtr=da->getConstPointer();
7446   int nbOfElems=da->getNbOfElems();
7447   for(int k=0;k<nbOfElems;k++)
7448     retPtr[k]=tmp[daPtr[k]];
7449   delete [] tmp;
7450   return ret;
7451 }
7452
7453 /*!
7454  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7455  * This method \b works \b for mesh sorted by type.
7456  * cells whose ids is in 'idsPerGeoType' array.
7457  * This method conserves coords and name of mesh.
7458  */
7459 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7460 {
7461   std::vector<int> code=getDistributionOfTypes();
7462   std::size_t nOfTypesInThis=code.size()/3;
7463   int sz=0,szOfType=0;
7464   for(std::size_t i=0;i<nOfTypesInThis;i++)
7465     {
7466       if(code[3*i]!=type)
7467         sz+=code[3*i+1];
7468       else
7469         szOfType=code[3*i+1];
7470     }
7471   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7472     if(*work<0 || *work>=szOfType)
7473       {
7474         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7475         oss << ". It should be in [0," << szOfType << ") !";
7476         throw INTERP_KERNEL::Exception(oss.str().c_str());
7477       }
7478   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7479   int *idsPtr=idsTokeep->getPointer();
7480   int offset=0;
7481   for(std::size_t i=0;i<nOfTypesInThis;i++)
7482     {
7483       if(code[3*i]!=type)
7484         for(int j=0;j<code[3*i+1];j++)
7485           *idsPtr++=offset+j;
7486       else
7487         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7488       offset+=code[3*i+1];
7489     }
7490   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7491   ret->copyTinyInfoFrom(this);
7492   return ret.retn();
7493 }
7494
7495 /*!
7496  * This method returns a vector of size 'this->getNumberOfCells()'.
7497  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7498  */
7499 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7500 {
7501   int ncell=getNumberOfCells();
7502   std::vector<bool> ret(ncell);
7503   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7504   const int *c=getNodalConnectivity()->getConstPointer();
7505   for(int i=0;i<ncell;i++)
7506     {
7507       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7508       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7509       ret[i]=cm.isQuadratic();
7510     }
7511   return ret;
7512 }
7513
7514 /*!
7515  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7516  */
7517 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7518 {
7519   if(other->getType()!=UNSTRUCTURED)
7520     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7521   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7522   return MergeUMeshes(this,otherC);
7523 }
7524
7525 /*!
7526  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7527  * computed by averaging coordinates of cell nodes, so this method is not a right
7528  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7529  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7530  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7531  *          components. The caller is to delete this array using decrRef() as it is
7532  *          no more needed.
7533  *  \throw If the coordinates array is not set.
7534  *  \throw If the nodal connectivity of cells is not defined.
7535  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7536  */
7537 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7538 {
7539   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7540   int spaceDim=getSpaceDimension();
7541   int nbOfCells=getNumberOfCells();
7542   ret->alloc(nbOfCells,spaceDim);
7543   ret->copyStringInfoFrom(*getCoords());
7544   double *ptToFill=ret->getPointer();
7545   const int *nodal=_nodal_connec->getConstPointer();
7546   const int *nodalI=_nodal_connec_index->getConstPointer();
7547   const double *coor=_coords->getConstPointer();
7548   for(int i=0;i<nbOfCells;i++)
7549     {
7550       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7551       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7552       ptToFill+=spaceDim;
7553     }
7554   return ret.retn();
7555 }
7556
7557 /*!
7558  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7559  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7560  * 
7561  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7562  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7563  * 
7564  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7565  * \throw If \a this is not fully defined (coordinates and connectivity)
7566  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7567  */
7568 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7569 {
7570   checkFullyDefined();
7571   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7572   int spaceDim=getSpaceDimension();
7573   int nbOfCells=getNumberOfCells();
7574   int nbOfNodes=getNumberOfNodes();
7575   ret->alloc(nbOfCells,spaceDim);
7576   double *ptToFill=ret->getPointer();
7577   const int *nodal=_nodal_connec->getConstPointer();
7578   const int *nodalI=_nodal_connec_index->getConstPointer();
7579   const double *coor=_coords->getConstPointer();
7580   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7581     {
7582       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7583       std::fill(ptToFill,ptToFill+spaceDim,0.);
7584       if(type!=INTERP_KERNEL::NORM_POLYHED)
7585         {
7586           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7587             {
7588               if(*conn>=0 && *conn<nbOfNodes)
7589                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7590               else
7591                 {
7592                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7593                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7594                 }
7595             }
7596           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7597           if(nbOfNodesInCell>0)
7598             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7599           else
7600             {
7601               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7602               throw INTERP_KERNEL::Exception(oss.str().c_str());
7603             }
7604         }
7605       else
7606         {
7607           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7608           s.erase(-1);
7609           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7610             {
7611               if(*it>=0 && *it<nbOfNodes)
7612                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7613               else
7614                 {
7615                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7616                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7617                 }
7618             }
7619           if(!s.empty())
7620             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7621           else
7622             {
7623               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7624               throw INTERP_KERNEL::Exception(oss.str().c_str());
7625             }
7626         }
7627     }
7628   return ret.retn();
7629 }
7630
7631 /*!
7632  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7633  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7634  * are specified via an array of cell ids. 
7635  *  \warning Validity of the specified cell ids is not checked! 
7636  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7637  *  \param [in] begin - an array of cell ids of interest.
7638  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7639  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7640  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7641  *          caller is to delete this array using decrRef() as it is no more needed. 
7642  *  \throw If the coordinates array is not set.
7643  *  \throw If the nodal connectivity of cells is not defined.
7644  *
7645  *  \if ENABLE_EXAMPLES
7646  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7647  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7648  *  \endif
7649  */
7650 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7651 {
7652   DataArrayDouble *ret=DataArrayDouble::New();
7653   int spaceDim=getSpaceDimension();
7654   int nbOfTuple=(int)std::distance(begin,end);
7655   ret->alloc(nbOfTuple,spaceDim);
7656   double *ptToFill=ret->getPointer();
7657   double *tmp=new double[spaceDim];
7658   const int *nodal=_nodal_connec->getConstPointer();
7659   const int *nodalI=_nodal_connec_index->getConstPointer();
7660   const double *coor=_coords->getConstPointer();
7661   for(const int *w=begin;w!=end;w++)
7662     {
7663       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7664       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7665       ptToFill+=spaceDim;
7666     }
7667   delete [] tmp;
7668   return ret;
7669 }
7670
7671 /*!
7672  * 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".
7673  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7674  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7675  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7676  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7677  * 
7678  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7679  * \throw If spaceDim!=3 or meshDim!=2.
7680  * \throw If connectivity of \a this is invalid.
7681  * \throw If connectivity of a cell in \a this points to an invalid node.
7682  */
7683 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7684 {
7685   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7686   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7687   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7688     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7689   ret->alloc(nbOfCells,4);
7690   double *retPtr(ret->getPointer());
7691   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7692   const double *coor(_coords->begin());
7693   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7694     {
7695       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7696       if(nodalI[1]-nodalI[0]>=3)
7697         {
7698           for(int j=0;j<3;j++)
7699             {
7700               int nodeId(nodal[nodalI[0]+1+j]);
7701               if(nodeId>=0 && nodeId<nbOfNodes)
7702                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7703               else
7704                 {
7705                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7706                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7707                 }
7708             }
7709         }
7710       else
7711         {
7712           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7713           throw INTERP_KERNEL::Exception(oss.str().c_str());
7714         }
7715       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7716       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7717     }
7718   return ret.retn();
7719 }
7720
7721 /*!
7722  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7723  * 
7724  */
7725 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7726 {
7727   if(!da)
7728     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7729   da->checkAllocated();
7730   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7731   ret->setCoords(da);
7732   int nbOfTuples=da->getNumberOfTuples();
7733   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7734   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7735   c->alloc(2*nbOfTuples,1);
7736   cI->alloc(nbOfTuples+1,1);
7737   int *cp=c->getPointer();
7738   int *cip=cI->getPointer();
7739   *cip++=0;
7740   for(int i=0;i<nbOfTuples;i++)
7741     {
7742       *cp++=INTERP_KERNEL::NORM_POINT1;
7743       *cp++=i;
7744       *cip++=2*(i+1);
7745     }
7746   ret->setConnectivity(c,cI,true);
7747   return ret.retn();
7748 }
7749 /*!
7750  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7751  * Cells and nodes of
7752  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7753  *  \param [in] mesh1 - the first mesh.
7754  *  \param [in] mesh2 - the second mesh.
7755  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7756  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7757  *          is no more needed.
7758  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7759  *  \throw If the coordinates array is not set in none of the meshes.
7760  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7761  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7762  */
7763 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7764 {
7765   std::vector<const MEDCouplingUMesh *> tmp(2);
7766   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7767   return MergeUMeshes(tmp);
7768 }
7769
7770 /*!
7771  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7772  * Cells and nodes of
7773  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7774  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7775  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7776  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7777  *          is no more needed.
7778  *  \throw If \a a.size() == 0.
7779  *  \throw If \a a[ *i* ] == NULL.
7780  *  \throw If the coordinates array is not set in none of the meshes.
7781  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7782  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7783  */
7784 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7785 {
7786   std::size_t sz=a.size();
7787   if(sz==0)
7788     return MergeUMeshesLL(a);
7789   for(std::size_t ii=0;ii<sz;ii++)
7790     if(!a[ii])
7791       {
7792         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7793         throw INTERP_KERNEL::Exception(oss.str().c_str());
7794       }
7795   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7796   std::vector< const MEDCouplingUMesh * > aa(sz);
7797   int spaceDim=-3;
7798   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7799     {
7800       const MEDCouplingUMesh *cur=a[i];
7801       const DataArrayDouble *coo=cur->getCoords();
7802       if(coo)
7803         spaceDim=coo->getNumberOfComponents();
7804     }
7805   if(spaceDim==-3)
7806     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7807   for(std::size_t i=0;i<sz;i++)
7808     {
7809       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7810       aa[i]=bb[i];
7811     }
7812   return MergeUMeshesLL(aa);
7813 }
7814
7815 /// @cond INTERNAL
7816
7817 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7818 {
7819   if(a.empty())
7820     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7821   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7822   int meshDim=(*it)->getMeshDimension();
7823   int nbOfCells=(*it)->getNumberOfCells();
7824   int meshLgth=(*it++)->getMeshLength();
7825   for(;it!=a.end();it++)
7826     {
7827       if(meshDim!=(*it)->getMeshDimension())
7828         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7829       nbOfCells+=(*it)->getNumberOfCells();
7830       meshLgth+=(*it)->getMeshLength();
7831     }
7832   std::vector<const MEDCouplingPointSet *> aps(a.size());
7833   std::copy(a.begin(),a.end(),aps.begin());
7834   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7835   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7836   ret->setCoords(pts);
7837   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7838   c->alloc(meshLgth,1);
7839   int *cPtr=c->getPointer();
7840   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7841   cI->alloc(nbOfCells+1,1);
7842   int *cIPtr=cI->getPointer();
7843   *cIPtr++=0;
7844   int offset=0;
7845   int offset2=0;
7846   for(it=a.begin();it!=a.end();it++)
7847     {
7848       int curNbOfCell=(*it)->getNumberOfCells();
7849       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7850       const int *curC=(*it)->_nodal_connec->getConstPointer();
7851       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7852       for(int j=0;j<curNbOfCell;j++)
7853         {
7854           const int *src=curC+curCI[j];
7855           *cPtr++=*src++;
7856           for(;src!=curC+curCI[j+1];src++,cPtr++)
7857             {
7858               if(*src!=-1)
7859                 *cPtr=*src+offset2;
7860               else
7861                 *cPtr=-1;
7862             }
7863         }
7864       offset+=curCI[curNbOfCell];
7865       offset2+=(*it)->getNumberOfNodes();
7866     }
7867   //
7868   ret->setConnectivity(c,cI,true);
7869   return ret.retn();
7870 }
7871
7872 /// @endcond
7873
7874 /*!
7875  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7876  * dimension and sharing the node coordinates array.
7877  * All cells of the first mesh precede all cells of the second mesh
7878  * within the result mesh. 
7879  *  \param [in] mesh1 - the first mesh.
7880  *  \param [in] mesh2 - the second mesh.
7881  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7882  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7883  *          is no more needed.
7884  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7885  *  \throw If the meshes do not share the node coordinates array.
7886  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7887  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7888  */
7889 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7890 {
7891   std::vector<const MEDCouplingUMesh *> tmp(2);
7892   tmp[0]=mesh1; tmp[1]=mesh2;
7893   return MergeUMeshesOnSameCoords(tmp);
7894 }
7895
7896 /*!
7897  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7898  * dimension and sharing the node coordinates array.
7899  * All cells of the *i*-th mesh precede all cells of the
7900  * (*i*+1)-th mesh within the result mesh.
7901  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7902  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7903  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7904  *          is no more needed.
7905  *  \throw If \a a.size() == 0.
7906  *  \throw If \a a[ *i* ] == NULL.
7907  *  \throw If the meshes do not share the node coordinates array.
7908  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7909  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7910  */
7911 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7912 {
7913   if(meshes.empty())
7914     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7915   for(std::size_t ii=0;ii<meshes.size();ii++)
7916     if(!meshes[ii])
7917       {
7918         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7919         throw INTERP_KERNEL::Exception(oss.str().c_str());
7920       }
7921   const DataArrayDouble *coords=meshes.front()->getCoords();
7922   int meshDim=meshes.front()->getMeshDimension();
7923   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7924   int meshLgth=0;
7925   int meshIndexLgth=0;
7926   for(;iter!=meshes.end();iter++)
7927     {
7928       if(coords!=(*iter)->getCoords())
7929         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7930       if(meshDim!=(*iter)->getMeshDimension())
7931         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7932       meshLgth+=(*iter)->getMeshLength();
7933       meshIndexLgth+=(*iter)->getNumberOfCells();
7934     }
7935   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7936   nodal->alloc(meshLgth,1);
7937   int *nodalPtr=nodal->getPointer();
7938   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7939   nodalIndex->alloc(meshIndexLgth+1,1);
7940   int *nodalIndexPtr=nodalIndex->getPointer();
7941   int offset=0;
7942   for(iter=meshes.begin();iter!=meshes.end();iter++)
7943     {
7944       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7945       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7946       int nbOfCells=(*iter)->getNumberOfCells();
7947       int meshLgth2=(*iter)->getMeshLength();
7948       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7949       if(iter!=meshes.begin())
7950         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7951       else
7952         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7953       offset+=meshLgth2;
7954     }
7955   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7956   ret->setName("merge");
7957   ret->setMeshDimension(meshDim);
7958   ret->setConnectivity(nodal,nodalIndex,true);
7959   ret->setCoords(coords);
7960   return ret;
7961 }
7962
7963 /*!
7964  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7965  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7966  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7967  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7968  * New" mode are returned for each input mesh.
7969  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7970  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7971  *          valid values [0,1,2], see zipConnectivityTraducer().
7972  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7973  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7974  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7975  *          no more needed.
7976  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7977  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7978  *          is no more needed.
7979  *  \throw If \a meshes.size() == 0.
7980  *  \throw If \a meshes[ *i* ] == NULL.
7981  *  \throw If the meshes do not share the node coordinates array.
7982  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7983  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7984  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7985  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7986  */
7987 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7988 {
7989   //All checks are delegated to MergeUMeshesOnSameCoords
7990   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7991   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7992   corr.resize(meshes.size());
7993   std::size_t nbOfMeshes=meshes.size();
7994   int offset=0;
7995   const int *o2nPtr=o2n->getConstPointer();
7996   for(std::size_t i=0;i<nbOfMeshes;i++)
7997     {
7998       DataArrayInt *tmp=DataArrayInt::New();
7999       int curNbOfCells=meshes[i]->getNumberOfCells();
8000       tmp->alloc(curNbOfCells,1);
8001       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8002       offset+=curNbOfCells;
8003       tmp->setName(meshes[i]->getName());
8004       corr[i]=tmp;
8005     }
8006   return ret.retn();
8007 }
8008
8009 /*!
8010  * Makes all given meshes share the nodal connectivity array. The common connectivity
8011  * array is created by concatenating the connectivity arrays of all given meshes. All
8012  * the given meshes must be of the same space dimension but dimension of cells **can
8013  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8014  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8015  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8016  *  \param [in,out] meshes - a vector of meshes to update.
8017  *  \throw If any of \a meshes is NULL.
8018  *  \throw If the coordinates array is not set in any of \a meshes.
8019  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8020  *  \throw If \a meshes are of different space dimension.
8021  */
8022 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8023 {
8024   std::size_t sz=meshes.size();
8025   if(sz==0 || sz==1)
8026     return;
8027   std::vector< const DataArrayDouble * > coords(meshes.size());
8028   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8029   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8030     {
8031       if((*it))
8032         {
8033           (*it)->checkConnectivityFullyDefined();
8034           const DataArrayDouble *coo=(*it)->getCoords();
8035           if(coo)
8036             *it2=coo;
8037           else
8038             {
8039               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8040               oss << " has no coordinate array defined !";
8041               throw INTERP_KERNEL::Exception(oss.str().c_str());
8042             }
8043         }
8044       else
8045         {
8046           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8047           oss << " is null !";
8048           throw INTERP_KERNEL::Exception(oss.str().c_str());
8049         }
8050     }
8051   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8052   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8053   int offset=(*it)->getNumberOfNodes();
8054   (*it++)->setCoords(res);
8055   for(;it!=meshes.end();it++)
8056     {
8057       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8058       (*it)->setCoords(res);
8059       (*it)->shiftNodeNumbersInConn(offset);
8060       offset+=oldNumberOfNodes;
8061     }
8062 }
8063
8064 /*!
8065  * Merges nodes coincident with a given precision within all given meshes that share
8066  * the nodal connectivity array. The given meshes **can be of different** mesh
8067  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8068  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8069  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8070  *  \param [in,out] meshes - a vector of meshes to update.
8071  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8072  *  \throw If any of \a meshes is NULL.
8073  *  \throw If the \a meshes do not share the same node coordinates array.
8074  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8075  */
8076 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8077 {
8078   if(meshes.empty())
8079     return ;
8080   std::set<const DataArrayDouble *> s;
8081   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8082     {
8083       if(*it)
8084         s.insert((*it)->getCoords());
8085       else
8086         {
8087           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 !";
8088           throw INTERP_KERNEL::Exception(oss.str().c_str());
8089         }
8090     }
8091   if(s.size()!=1)
8092     {
8093       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 !";
8094       throw INTERP_KERNEL::Exception(oss.str().c_str());
8095     }
8096   const DataArrayDouble *coo=*(s.begin());
8097   if(!coo)
8098     return;
8099   //
8100   DataArrayInt *comm,*commI;
8101   coo->findCommonTuples(eps,-1,comm,commI);
8102   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8103   int oldNbOfNodes=coo->getNumberOfTuples();
8104   int newNbOfNodes;
8105   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8106   if(oldNbOfNodes==newNbOfNodes)
8107     return ;
8108   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8109   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8110     {
8111       (*it)->renumberNodesInConn(o2n->getConstPointer());
8112       (*it)->setCoords(newCoords);
8113     } 
8114 }
8115
8116 /*!
8117  * 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.
8118  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8119  * \param isQuad specifies the policy of connectivity.
8120  * @ret in/out parameter in which the result will be append
8121  */
8122 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8123 {
8124   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8125   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8126   ret.push_back(cm.getExtrudedType());
8127   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8128   switch(flatType)
8129   {
8130     case INTERP_KERNEL::NORM_POINT1:
8131       {
8132         ret.push_back(connBg[1]);
8133         ret.push_back(connBg[1]+nbOfNodesPerLev);
8134         break;
8135       }
8136     case INTERP_KERNEL::NORM_SEG2:
8137       {
8138         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8139         ret.insert(ret.end(),conn,conn+4);
8140         break;
8141       }
8142     case INTERP_KERNEL::NORM_SEG3:
8143       {
8144         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8145         ret.insert(ret.end(),conn,conn+8);
8146         break;
8147       }
8148     case INTERP_KERNEL::NORM_QUAD4:
8149       {
8150         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8151         ret.insert(ret.end(),conn,conn+8);
8152         break;
8153       }
8154     case INTERP_KERNEL::NORM_TRI3:
8155       {
8156         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8157         ret.insert(ret.end(),conn,conn+6);
8158         break;
8159       }
8160     case INTERP_KERNEL::NORM_TRI6:
8161       {
8162         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,
8163           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8164         ret.insert(ret.end(),conn,conn+15);
8165         break;
8166       }
8167     case INTERP_KERNEL::NORM_QUAD8:
8168       {
8169         int conn[20]={
8170           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8171           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8172           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8173         };
8174         ret.insert(ret.end(),conn,conn+20);
8175         break;
8176       }
8177     case INTERP_KERNEL::NORM_POLYGON:
8178       {
8179         std::back_insert_iterator< std::vector<int> > ii(ret);
8180         std::copy(connBg+1,connEnd,ii);
8181         *ii++=-1;
8182         std::reverse_iterator<const int *> rConnBg(connEnd);
8183         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8184         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8185         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8186         for(std::size_t i=0;i<nbOfRadFaces;i++)
8187           {
8188             *ii++=-1;
8189             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8190             std::copy(conn,conn+4,ii);
8191           }
8192         break;
8193       }
8194     default:
8195       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8196   }
8197 }
8198
8199 /*!
8200  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8201  */
8202 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8203 {
8204   std::size_t i, ip1;
8205   double v[3]={0.,0.,0.};
8206   std::size_t sz=std::distance(begin,end);
8207   if(isQuadratic)
8208     sz/=2;
8209   for(i=0;i<sz;i++)
8210     {
8211       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];
8212       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8213       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8214     }
8215   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8216
8217   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8218   // SEG3 forming a circle):
8219   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8220     {
8221       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8222       for(std::size_t j=0;j<sz;j++)
8223         {
8224           if (j%2)  // current point i is quadratic, next point i+1 is standard
8225             {
8226               i = sz+j;
8227               ip1 = (j+1)%sz; // ip1 = "i+1"
8228             }
8229           else      // current point i is standard, next point i+1 is quadratic
8230             {
8231               i = j;
8232               ip1 = j+sz;
8233             }
8234           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8235           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8236           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8237         }
8238       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8239     }
8240   return (ret>0.);
8241 }
8242
8243 /*!
8244  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8245  */
8246 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8247 {
8248   std::vector<std::pair<int,int> > edges;
8249   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8250   const int *bgFace=begin;
8251   for(std::size_t i=0;i<nbOfFaces;i++)
8252     {
8253       const int *endFace=std::find(bgFace+1,end,-1);
8254       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8255       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8256         {
8257           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8258           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8259             return false;
8260           edges.push_back(p1);
8261         }
8262       bgFace=endFace+1;
8263     }
8264   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8265 }
8266
8267 /*!
8268  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8269  */
8270 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8271 {
8272   double vec0[3],vec1[3];
8273   std::size_t sz=std::distance(begin,end);
8274   if(sz%2!=0)
8275     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8276   int nbOfNodes=(int)sz/2;
8277   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8278   const double *pt0=coords+3*begin[0];
8279   const double *pt1=coords+3*begin[nbOfNodes];
8280   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8281   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8282 }
8283
8284 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8285 {
8286   std::size_t sz=std::distance(begin,end);
8287   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8288   std::size_t nbOfNodes(sz/2);
8289   std::copy(begin,end,(int *)tmp);
8290   for(std::size_t j=1;j<nbOfNodes;j++)
8291     {
8292       begin[j]=tmp[nbOfNodes-j];
8293       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8294     }
8295 }
8296
8297 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8298 {
8299   std::size_t sz=std::distance(begin,end);
8300   if(sz!=4)
8301     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8302   double vec0[3],vec1[3];
8303   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8304   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]; 
8305   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;
8306 }
8307
8308 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8309 {
8310   std::size_t sz=std::distance(begin,end);
8311   if(sz!=5)
8312     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8313   double vec0[3];
8314   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8315   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8316   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8317 }
8318
8319 /*!
8320  * 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 ) 
8321  * 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
8322  * a 2D space.
8323  *
8324  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8325  * \param [in] coords the coordinates with nb of components exactly equal to 3
8326  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8327  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8328  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8329  */
8330 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8331 {
8332   int nbFaces=std::count(begin+1,end,-1)+1;
8333   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8334   double *vPtr=v->getPointer();
8335   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8336   double *pPtr=p->getPointer();
8337   const int *stFaceConn=begin+1;
8338   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8339     {
8340       const int *endFaceConn=std::find(stFaceConn,end,-1);
8341       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8342       stFaceConn=endFaceConn+1;
8343     }
8344   pPtr=p->getPointer(); vPtr=v->getPointer();
8345   DataArrayInt *comm1=0,*commI1=0;
8346   v->findCommonTuples(eps,-1,comm1,commI1);
8347   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8348   const int *comm1Ptr=comm1->getConstPointer();
8349   const int *commI1Ptr=commI1->getConstPointer();
8350   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8351   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8352   //
8353   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8354   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8355   mm->finishInsertingCells();
8356   //
8357   for(int i=0;i<nbOfGrps1;i++)
8358     {
8359       int vecId=comm1Ptr[commI1Ptr[i]];
8360       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8361       DataArrayInt *comm2=0,*commI2=0;
8362       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8363       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8364       const int *comm2Ptr=comm2->getConstPointer();
8365       const int *commI2Ptr=commI2->getConstPointer();
8366       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8367       for(int j=0;j<nbOfGrps2;j++)
8368         {
8369           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8370             {
8371               res->insertAtTheEnd(begin,end);
8372               res->pushBackSilent(-1);
8373             }
8374           else
8375             {
8376               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8377               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8378               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8379               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8380               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8381               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8382               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8383               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8384               const int *idsNodePtr=idsNode->getConstPointer();
8385               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];
8386               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8387               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8388               if(std::abs(norm)>eps)
8389                 {
8390                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8391                   mm3->rotate(center,vec,angle);
8392                 }
8393               mm3->changeSpaceDimension(2);
8394               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8395               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8396               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8397               int nbOfCells=mm4->getNumberOfCells();
8398               for(int k=0;k<nbOfCells;k++)
8399                 {
8400                   int l=0;
8401                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8402                     res->pushBackSilent(idsNodePtr[*work]);
8403                   res->pushBackSilent(-1);
8404                 }
8405             }
8406         }
8407     }
8408   res->popBackSilent();
8409 }
8410
8411 /*!
8412  * 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
8413  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8414  * 
8415  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8416  * \param [in] coords coordinates expected to have 3 components.
8417  * \param [in] begin start of the nodal connectivity of the face.
8418  * \param [in] end end of the nodal connectivity (excluded) of the face.
8419  * \param [out] v the normalized vector of size 3
8420  * \param [out] p the pos of plane
8421  */
8422 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8423 {
8424   std::size_t nbPoints=std::distance(begin,end);
8425   if(nbPoints<3)
8426     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8427   double vec[3]={0.,0.,0.};
8428   std::size_t j=0;
8429   bool refFound=false;
8430   for(;j<nbPoints-1 && !refFound;j++)
8431     {
8432       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8433       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8434       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8435       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8436       if(norm>eps)
8437         {
8438           refFound=true;
8439           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8440         }
8441     }
8442   for(std::size_t i=j;i<nbPoints-1;i++)
8443     {
8444       double curVec[3];
8445       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8446       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8447       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8448       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8449       if(norm<eps)
8450         continue;
8451       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8452       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];
8453       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8454       if(norm>eps)
8455         {
8456           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8457           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8458           return ;
8459         }
8460     }
8461   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8462 }
8463
8464 /*!
8465  * This method tries to obtain a well oriented polyhedron.
8466  * If the algorithm fails, an exception will be thrown.
8467  */
8468 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8469 {
8470   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8471   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8472   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8473   isPerm[0]=true;
8474   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8475   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8476   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8477   //
8478   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8479     {
8480       bgFace=begin;
8481       std::size_t smthChanged=0;
8482       for(std::size_t i=0;i<nbOfFaces;i++)
8483         {
8484           endFace=std::find(bgFace+1,end,-1);
8485           nbOfEdgesInFace=std::distance(bgFace,endFace);
8486           if(!isPerm[i])
8487             {
8488               bool b;
8489               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8490                 {
8491                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8492                   std::pair<int,int> p2(p1.second,p1.first);
8493                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8494                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8495                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8496                 }
8497               if(isPerm[i])
8498                 { 
8499                   if(!b)
8500                     std::reverse(bgFace+1,endFace);
8501                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8502                     {
8503                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8504                       std::pair<int,int> p2(p1.second,p1.first);
8505                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8506                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8507                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8508                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8509                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8510                       if(it!=edgesOK.end())
8511                         {
8512                           edgesOK.erase(it);
8513                           edgesFinished.push_back(p1);
8514                         }
8515                       else
8516                         edgesOK.push_back(p1);
8517                     }
8518                 }
8519             }
8520           bgFace=endFace+1;
8521         }
8522       if(smthChanged==0)
8523         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8524     }
8525   if(!edgesOK.empty())
8526     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8527   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8528     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8529       bgFace=begin;
8530       for(std::size_t i=0;i<nbOfFaces;i++)
8531         {
8532           endFace=std::find(bgFace+1,end,-1);
8533           std::reverse(bgFace+1,endFace);
8534           bgFace=endFace+1;
8535         }
8536     }
8537 }
8538
8539 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8540 {
8541   int nbOfNodesExpected(skin->getNumberOfNodes());
8542   const int *n2oPtr(n2o->getConstPointer());
8543   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8544   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8545   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8546   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8547   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8548   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8549   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8550   if(nbOfNodesExpected<1)
8551     return ret.retn();
8552   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8553   *work++=n2oPtr[prevNode];
8554   for(int i=1;i<nbOfNodesExpected;i++)
8555     {
8556       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8557         {
8558           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8559           conn.erase(prevNode);
8560           if(conn.size()==1)
8561             {
8562               int curNode(*(conn.begin()));
8563               *work++=n2oPtr[curNode];
8564               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8565               shar.erase(prevCell);
8566               if(shar.size()==1)
8567                 {
8568                   prevCell=*(shar.begin());
8569                   prevNode=curNode;
8570                 }
8571               else
8572                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8573             }
8574           else
8575             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8576         }
8577       else
8578         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8579     }
8580   return ret.retn();
8581 }
8582
8583 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8584 {
8585   int nbOfNodesExpected(skin->getNumberOfNodes());
8586   int nbOfTurn(nbOfNodesExpected/2);
8587   const int *n2oPtr(n2o->getConstPointer());
8588   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8589   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8590   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8591   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8592   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8593   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8594   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8595   if(nbOfNodesExpected<1)
8596     return ret.retn();
8597   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8598   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8599   for(int i=1;i<nbOfTurn;i++)
8600     {
8601       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8602         {
8603           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8604           conn.erase(prevNode);
8605           if(conn.size()==1)
8606             {
8607               int curNode(*(conn.begin()));
8608               *work=n2oPtr[curNode];
8609               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8610               shar.erase(prevCell);
8611               if(shar.size()==1)
8612                 {
8613                   int curCell(*(shar.begin()));
8614                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8615                   prevCell=curCell;
8616                   prevNode=curNode;
8617                   work++;
8618                 }
8619               else
8620                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8621             }
8622           else
8623             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8624         }
8625       else
8626         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8627     }
8628   return ret.retn();
8629 }
8630
8631 /*!
8632  * This method makes the assumption spacedimension == meshdimension == 2.
8633  * This method works only for linear cells.
8634  * 
8635  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8636  */
8637 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8638 {
8639   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8640     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8641   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8642   int oldNbOfNodes(skin->getNumberOfNodes());
8643   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8644   int nbOfNodesExpected(skin->getNumberOfNodes());
8645   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8646   int nbCells(skin->getNumberOfCells());
8647   if(nbCells==nbOfNodesExpected)
8648     return buildUnionOf2DMeshLinear(skin,n2o);
8649   else if(2*nbCells==nbOfNodesExpected)
8650     return buildUnionOf2DMeshQuadratic(skin,n2o);
8651   else
8652     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8653 }
8654
8655 /*!
8656  * This method makes the assumption spacedimension == meshdimension == 3.
8657  * This method works only for linear cells.
8658  * 
8659  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8660  */
8661 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8662 {
8663   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8664     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8665   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8666   const int *conn=m->getNodalConnectivity()->getConstPointer();
8667   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8668   int nbOfCells=m->getNumberOfCells();
8669   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8670   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8671   if(nbOfCells<1)
8672     return ret.retn();
8673   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8674   for(int i=1;i<nbOfCells;i++)
8675     {
8676       *work++=-1;
8677       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8678     }
8679   return ret.retn();
8680 }
8681
8682 /*!
8683  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8684  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8685  */
8686 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8687 {
8688   double *w=zipFrmt;
8689   if(spaceDim==3)
8690     for(int i=0;i<nbOfNodesInCell;i++)
8691       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8692   else if(spaceDim==2)
8693     {
8694       for(int i=0;i<nbOfNodesInCell;i++)
8695         {
8696           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8697           *w++=0.;
8698         }
8699     }
8700   else
8701     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8702 }
8703
8704 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8705 {
8706   int nbOfCells=getNumberOfCells();
8707   if(nbOfCells<=0)
8708     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8709   static const int PARAMEDMEM2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,34,23,28,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,29,-1,-1,25,42,36,4};
8710   ofs << "  <" << getVTKDataSetType() << ">\n";
8711   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8712   ofs << "      <PointData>\n" << pointData << std::endl;
8713   ofs << "      </PointData>\n";
8714   ofs << "      <CellData>\n" << cellData << std::endl;
8715   ofs << "      </CellData>\n";
8716   ofs << "      <Points>\n";
8717   if(getSpaceDimension()==3)
8718     _coords->writeVTK(ofs,8,"Points",byteData);
8719   else
8720     {
8721       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8722       coo->writeVTK(ofs,8,"Points",byteData);
8723     }
8724   ofs << "      </Points>\n";
8725   ofs << "      <Cells>\n";
8726   const int *cPtr=_nodal_connec->getConstPointer();
8727   const int *cIPtr=_nodal_connec_index->getConstPointer();
8728   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8729   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8730   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8731   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8732   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8733   int szFaceOffsets=0,szConn=0;
8734   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8735     {
8736       *w2=cPtr[cIPtr[i]];
8737       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8738         {
8739           *w1=-1;
8740           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8741           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8742         }
8743       else
8744         {
8745           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8746           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8747           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8748           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8749           w4=std::copy(c.begin(),c.end(),w4);
8750         }
8751     }
8752   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8753   types->writeVTK(ofs,8,"UInt8","types",byteData);
8754   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8755   if(szFaceOffsets!=0)
8756     {//presence of Polyhedra
8757       connectivity->reAlloc(szConn);
8758       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8759       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8760       w1=faces->getPointer();
8761       for(int i=0;i<nbOfCells;i++)
8762         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8763           {
8764             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8765             *w1++=nbFaces;
8766             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8767             for(int j=0;j<nbFaces;j++)
8768               {
8769                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8770                 *w1++=(int)std::distance(w6,w5);
8771                 w1=std::copy(w6,w5,w1);
8772                 w6=w5+1;
8773               }
8774           }
8775       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8776     }
8777   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8778   ofs << "      </Cells>\n";
8779   ofs << "    </Piece>\n";
8780   ofs << "  </" << getVTKDataSetType() << ">\n";
8781 }
8782
8783 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8784 {
8785   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8786   if(_mesh_dim==-2)
8787     { stream << " Not set !"; return ; }
8788   stream << " Mesh dimension : " << _mesh_dim << ".";
8789   if(_mesh_dim==-1)
8790     return ;
8791   if(!_coords)
8792     { stream << " No coordinates set !"; return ; }
8793   if(!_coords->isAllocated())
8794     { stream << " Coordinates set but not allocated !"; return ; }
8795   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8796   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8797   if(!_nodal_connec_index)
8798     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8799   if(!_nodal_connec_index->isAllocated())
8800     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8801   int lgth=_nodal_connec_index->getNumberOfTuples();
8802   int cpt=_nodal_connec_index->getNumberOfComponents();
8803   if(cpt!=1 || lgth<1)
8804     return ;
8805   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8806 }
8807
8808 std::string MEDCouplingUMesh::getVTKDataSetType() const
8809 {
8810   return std::string("UnstructuredGrid");
8811 }
8812
8813 std::string MEDCouplingUMesh::getVTKFileExtension() const
8814 {
8815   return std::string("vtu");
8816 }
8817
8818 /*!
8819  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8820  * returns a result mesh constituted by polygons.
8821  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8822  * all nodes from m2.
8823  * The meshes should be in 2D space. In
8824  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8825  * meshes.
8826  *  \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
8827  *                      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)
8828  *  \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
8829  *                      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)
8830  *  \param [in] eps - precision used to detect coincident mesh entities.
8831  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8832  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8833  *         this array using decrRef() as it is no more needed.
8834  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8835  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8836  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8837  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8838  *         it is no more needed.  
8839  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8840  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8841  *         is no more needed.  
8842  *  \throw If the coordinates array is not set in any of the meshes.
8843  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8844  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8845  *
8846  *  \sa conformize2D, mergeNodes
8847  */
8848 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8849                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8850 {
8851   if(!m1 || !m2)
8852     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8853   m1->checkFullyDefined();
8854   m2->checkFullyDefined();
8855   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8856     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8857
8858   // Step 1: compute all edge intersections (new nodes)
8859   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8860   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8861   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8862   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8863   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8864                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8865                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8866   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8867   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8868   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8869
8870   // Step 2: re-order newly created nodes according to the ordering found in m2
8871   std::vector< std::vector<int> > intersectEdge2;
8872   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8873   subDiv2.clear(); dd5=0; dd6=0;
8874
8875   // Step 3:
8876   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8877   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8878   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8879                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8880
8881   // Step 4: Prepare final result:
8882   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8883   addCooDa->alloc((int)(addCoo.size())/2,2);
8884   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8885   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8886   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8887   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8888   std::vector<const DataArrayDouble *> coordss(4);
8889   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8890   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8891   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8892   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8893   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8894   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8895   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8896   ret->setConnectivity(conn,connI,true);
8897   ret->setCoords(coo);
8898   cellNb1=c1.retn(); cellNb2=c2.retn();
8899   return ret.retn();
8900 }
8901
8902 /// @cond INTERNAL
8903
8904 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8905 {
8906   if(candidates.empty())
8907     return false;
8908   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8909     {
8910       const std::vector<int>& pool(intersectEdge1[*it]);
8911       int tmp[2]; tmp[0]=start; tmp[1]=stop;
8912       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8913         {
8914           retVal=*it+1;
8915           return true;
8916         }
8917       tmp[0]=stop; tmp[1]=start;
8918       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8919         {
8920           retVal=-*it-1;
8921           return true;
8922         }
8923     }
8924   return false;
8925 }
8926
8927 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,
8928                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
8929 {
8930   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
8931   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
8932   int nCells(mesh1D->getNumberOfCells());
8933   if(nCells!=(int)intersectEdge2.size())
8934     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8935   const DataArrayDouble *coo2(mesh1D->getCoords());
8936   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8937   const double *coo2Ptr(coo2->begin());
8938   int offset1(coords1->getNumberOfTuples());
8939   int offset2(offset1+coo2->getNumberOfTuples());
8940   int offset3(offset2+addCoo.size()/2);
8941   std::vector<double> addCooQuad;
8942   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8943   int tmp[4],cicnt(0),kk(0);
8944   for(int i=0;i<nCells;i++)
8945     {
8946       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
8947       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8948       const std::vector<int>& subEdges(intersectEdge2[i]);
8949       int nbSubEdge(subEdges.size()/2);
8950       for(int j=0;j<nbSubEdge;j++,kk++)
8951         {
8952           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n1(MEDCouplingUMeshBuildQPNode(subEdges[2*j],coords1->begin(),offset1,coo2Ptr,offset2,addCoo)),n2(MEDCouplingUMeshBuildQPNode(subEdges[2*j+1],coords1->begin(),offset1,coo2Ptr,offset2,addCoo));
8953           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8954           INTERP_KERNEL::Edge *e2Ptr(e2);
8955           std::map<int,int>::const_iterator itm;
8956           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8957             {
8958               tmp[0]=INTERP_KERNEL::NORM_SEG3;
8959               itm=mergedNodes.find(subEdges[2*j]);
8960               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8961               itm=mergedNodes.find(subEdges[2*j+1]);
8962               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8963               tmp[3]=offset3+(int)addCooQuad.size()/2;
8964               double tmp2[2];
8965               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
8966               cicnt+=4;
8967               cOut->insertAtTheEnd(tmp,tmp+4);
8968               ciOut->pushBackSilent(cicnt);
8969             }
8970           else
8971             {
8972               tmp[0]=INTERP_KERNEL::NORM_SEG2;
8973               itm=mergedNodes.find(subEdges[2*j]);
8974               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
8975               itm=mergedNodes.find(subEdges[2*j+1]);
8976               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
8977               cicnt+=3;
8978               cOut->insertAtTheEnd(tmp,tmp+3);
8979               ciOut->pushBackSilent(cicnt);
8980             }
8981           int tmp00;
8982           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
8983             {
8984               idsInRetColinear->pushBackSilent(kk);
8985               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
8986             }
8987         }
8988       e->decrRef();
8989     }
8990   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8991   ret->setConnectivity(cOut,ciOut,true);
8992   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8993   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8994   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8995   std::vector<const DataArrayDouble *> coordss(4);
8996   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8997   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8998   ret->setCoords(arr);
8999   return ret.retn();
9000 }
9001
9002 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9003 {
9004   std::vector<int> allEdges;
9005   for(const int *it2(descBg);it2!=descEnd;it2++)
9006     {
9007       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9008       if(*it2>0)
9009         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9010       else
9011         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9012     }
9013   std::size_t nb(allEdges.size());
9014   if(nb%2!=0)
9015     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9016   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9017   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9018   ret->setCoords(coords);
9019   ret->allocateCells(1);
9020   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9021   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9022     connOut[kk]=allEdges[2*kk];
9023   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9024   return ret.retn();
9025 }
9026
9027 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9028 {
9029   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9030   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9031   std::size_t ii(0);
9032   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9033   if(sz!=std::distance(descBg,descEnd))
9034     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9035   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9036   std::vector<int> allEdges,centers;
9037   const double *coordsPtr(coords->begin());
9038   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9039   int offset(coords->getNumberOfTuples());
9040   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9041     {
9042       INTERP_KERNEL::NormalizedCellType typeOfSon;
9043       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9044       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9045       if(*it2>0)
9046         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9047       else
9048         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9049       if(edge1.size()==2)
9050         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9051       else
9052         {//the current edge has been subsplit -> create corresponding centers.
9053           std::size_t nbOfCentersToAppend(edge1.size()/2);
9054           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9055           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9056           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9057           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9058             {
9059               double tmpp[2];
9060               const double *aa(coordsPtr+2*(*it3++));
9061               const double *bb(coordsPtr+2*(*it3++));
9062               ee->getMiddleOfPoints(aa,bb,tmpp);
9063               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9064               centers.push_back(offset+k);
9065             }
9066         }
9067     }
9068   std::size_t nb(allEdges.size());
9069   if(nb%2!=0)
9070     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9071   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9072   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9073   if(addCoo->empty())
9074     ret->setCoords(coords);
9075   else
9076     {
9077       addCoo->rearrange(2);
9078       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9079       ret->setCoords(addCoo);
9080     }
9081   ret->allocateCells(1);
9082   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9083   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9084     connOut[kk]=allEdges[2*kk];
9085   connOut.insert(connOut.end(),centers.begin(),centers.end());
9086   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9087   return ret.retn();
9088 }
9089
9090 /*!
9091  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9092  * of those edges.
9093  *
9094  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9095  */
9096 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9097 {
9098   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9099   if(!cm.isQuadratic())
9100     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9101   else
9102     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9103 }
9104
9105 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9106 {
9107   bool isQuad(false);
9108   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9109     {
9110       const INTERP_KERNEL::Edge *ee(*it);
9111       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9112         isQuad=true;
9113     }
9114   if(!isQuad)
9115     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9116   else
9117     {
9118       const double *coo(mesh2D->getCoords()->begin());
9119       std::size_t sz(conn.size());
9120       std::vector<double> addCoo;
9121       std::vector<int> conn2(conn);
9122       int offset(mesh2D->getNumberOfNodes());
9123       for(std::size_t i=0;i<sz;i++)
9124         {
9125           double tmp[2];
9126           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9127           addCoo.insert(addCoo.end(),tmp,tmp+2);
9128           conn2.push_back(offset+(int)i);
9129         }
9130       mesh2D->getCoords()->rearrange(1);
9131       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9132       mesh2D->getCoords()->rearrange(2);
9133       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9134     }
9135 }
9136
9137 /*!
9138  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9139  *
9140  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9141  * a set of edges defined in \a splitMesh1D.
9142  */
9143 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9144                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9145 {
9146   std::size_t nb(edge1Bis.size()/2);
9147   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9148   int iEnd(splitMesh1D->getNumberOfCells());
9149   if(iEnd==0)
9150     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9151   std::size_t ii,jj;
9152   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9153   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9154   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9155   //
9156   if(jj==nb)
9157     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9158       out0.resize(1); out1.resize(1);
9159       std::vector<int>& connOut(out0[0]);
9160       connOut.resize(nbOfEdgesOf2DCellSplit);
9161       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9162       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9163       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9164         {
9165           connOut[kk]=edge1Bis[2*kk];
9166           edgesPtr[kk]=edge1BisPtr[2*kk];
9167         }
9168     }
9169   else
9170     {
9171       // [i,iEnd[ contains the
9172       out0.resize(2); out1.resize(2);
9173       std::vector<int>& connOutLeft(out0[0]);
9174       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9175       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9176       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9177       for(std::size_t k=ii;k<jj+1;k++)
9178         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9179       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9180       for(int ik=0;ik<iEnd;ik++)
9181         {
9182           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9183           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9184           ees[ik]=ee;
9185         }
9186       for(int ik=iEnd-1;ik>=0;ik--)
9187         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9188       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9189         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9190       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9191       for(int ik=0;ik<iEnd;ik++)
9192         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9193       eright.insert(eright.end(),ees.begin(),ees.end());
9194     }
9195 }
9196
9197 /// @endcond
9198
9199 /// @cond INTERNAL
9200
9201 struct CellInfo
9202 {
9203 public:
9204   CellInfo() { }
9205   CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9206 public:
9207   std::vector<int> _edges;
9208   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9209 };
9210
9211 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9212 {
9213   std::size_t nbe(edges.size());
9214   std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9215   for(std::size_t i=0;i<nbe;i++)
9216     {
9217       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9218       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9219     }
9220   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9221   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9222   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9223 }
9224
9225 class EdgeInfo
9226 {
9227 public:
9228   EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9229   EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9230   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9231   void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9232   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9233 private:
9234   int _istart;
9235   int _iend;
9236   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9237   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9238   int _left;
9239   int _right;
9240 };
9241
9242 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9243 {
9244   const MEDCouplingUMesh *mesh(_mesh);
9245   if(mesh)
9246     return ;
9247   if(_right<pos)
9248     return ;
9249   if(_left>pos)
9250     { _left++; _right++; return ; }
9251   if(_right==pos)
9252     {
9253       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9254       if((isLeft && isRight) || (!isLeft && !isRight))
9255         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9256       if(isLeft)
9257         return ;
9258       if(isRight)
9259         {
9260           _right++;
9261           return ;
9262         }
9263     }
9264   if(_left==pos)
9265     {
9266       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9267       if((isLeft && isRight) || (!isLeft && !isRight))
9268         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9269       if(isLeft)
9270         {
9271           _right++;
9272           return ;
9273         }
9274       if(isRight)
9275         {
9276           _left++;
9277           _right++;
9278           return ;
9279         }
9280     }
9281 }
9282
9283 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9284 {
9285   const MEDCouplingUMesh *mesh(_mesh);
9286   if(!mesh)
9287     {
9288       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9289     }
9290   else
9291     {// not fully splitting cell case
9292       if(mesh2D->getNumberOfCells()==1)
9293         {//little optimization. 1 cell no need to find in which cell mesh is !
9294           neighbors[0]=offset; neighbors[1]=offset;
9295           return;
9296         }
9297       else
9298         {
9299           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9300           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9301           if(cellId==-1)
9302             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9303           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9304         }
9305     }
9306 }
9307
9308 class VectorOfCellInfo
9309 {
9310 public:
9311   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9312   std::size_t size() const { return _pool.size(); }
9313   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9314   void setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs);
9315   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9316   const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9317   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9318   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9319 private:
9320   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9321   void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9322   const CellInfo& get(int pos) const;
9323   CellInfo& get(int pos);
9324 private:
9325   std::vector<CellInfo> _pool;
9326   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9327   std::vector<EdgeInfo> _edge_info;
9328 };
9329
9330 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9331 {
9332   _pool[0]._edges=edges;
9333   _pool[0]._edges_ptr=edgesPtr;
9334 }
9335
9336 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9337 {
9338   if(_pool.empty())
9339     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9340   if(_pool.size()==1)
9341     return 0;
9342   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9343   if(!zeMesh)
9344     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9345   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9346   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9347 }
9348
9349 void VectorOfCellInfo::setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs)
9350 {
9351   get(pos);//to check pos
9352   bool isFast(pos==0 && _pool.size()==1);
9353   std::size_t sz(edges.size());
9354   // dealing with edges
9355   if(sz==1)
9356     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9357   else
9358     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9359   //
9360   std::vector<CellInfo> pool(_pool.size()-1+sz);
9361   for(int i=0;i<pos;i++)
9362     pool[i]=_pool[i];
9363   for(std::size_t j=0;j<sz;j++)
9364     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9365   for(int i=pos+1;i<(int)_pool.size();i++)
9366     pool[i+sz-1]=_pool[i];
9367   _pool=pool;
9368   //
9369   if(sz==2)
9370     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9371   //
9372   if(isFast)
9373     {
9374       _ze_mesh=mesh;
9375       return ;
9376     }
9377   //
9378   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9379   if(pos>0)
9380     {
9381       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9382       ms.push_back(elt);
9383     }
9384   ms.push_back(mesh);
9385   if(pos<_ze_mesh->getNumberOfCells()-1)
9386   {
9387     MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9388     ms.push_back(elt);
9389   }
9390   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9391   for(std::size_t j=0;j<ms2.size();j++)
9392     ms2[j]=ms[j];
9393   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9394 }
9395
9396 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9397 {
9398   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9399 }
9400
9401 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9402 {
9403   if(pos<0)
9404     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9405   int ret(0);
9406   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9407     {
9408       if((*it).isInMyRange(pos))
9409         return ret;
9410     }
9411   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9412 }
9413
9414 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9415 {
9416   get(pos);//to check;
9417   if(_edge_info.empty())
9418     return ;
9419   std::size_t sz(_edge_info.size()-1);
9420   for(std::size_t i=0;i<sz;i++)
9421     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9422 }
9423
9424 const CellInfo& VectorOfCellInfo::get(int pos) const
9425 {
9426   if(pos<0 || pos>=(int)_pool.size())
9427     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9428   return _pool[pos];
9429 }
9430
9431 CellInfo& VectorOfCellInfo::get(int pos)
9432 {
9433   if(pos<0 || pos>=(int)_pool.size())
9434     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9435   return _pool[pos];
9436 }
9437
9438 /*!
9439  * Given :
9440  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9441  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9442  *
9443  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9444  *
9445  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9446  *
9447  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9448  */
9449 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9450                                          MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9451 {
9452   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9453   if(nbCellsInSplitMesh1D==0)
9454     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9455   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9456   std::size_t nb(allEdges.size()),jj;
9457   if(nb%2!=0)
9458     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9459   std::vector<int> edge1Bis(nb*2);
9460   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9461   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9462   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9463   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9464   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9465   //
9466   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9467   int *idsLeftRightPtr(idsLeftRight->getPointer());
9468   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9469   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9470     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9471       int iEnd(iStart);
9472       for(;iEnd<nbCellsInSplitMesh1D;)
9473         {
9474           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9475           if(jj!=nb)
9476             break;
9477           else
9478             iEnd++;
9479         }
9480       if(iEnd<nbCellsInSplitMesh1D)
9481         iEnd++;
9482       //
9483       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9484       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9485       //
9486       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9487       retTmp->setCoords(splitMesh1D->getCoords());
9488       retTmp->allocateCells();
9489
9490       std::vector< std::vector<int> > out0;
9491       std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9492
9493       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9494       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9495         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9496       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9497       //
9498       iStart=iEnd;
9499     }
9500   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9501     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9502   return pool.getZeMesh().retn();
9503 }
9504
9505 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9506                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9507                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9508 {
9509   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9510   //
9511   std::vector<int> allEdges;
9512   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9513   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9514     {
9515       int edgeId(std::abs(*it)-1);
9516       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9517       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9518       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9519       if(*it>0)
9520         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9521       else
9522         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9523       std::size_t sz(edge1.size());
9524       for(std::size_t cnt=0;cnt<sz;cnt++)
9525         allEdgesPtr.push_back(ee);
9526     }
9527   //
9528   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9529 }
9530
9531 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9532 {
9533   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9534     {//easy case comparison not
9535       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9536     }
9537   else if(typ1.isQuadratic() && typ2.isQuadratic())
9538     {
9539       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9540       if(!status0)
9541         return false;
9542       if(conn1[2]==conn2[2])
9543         return true;
9544       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9545       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9546       return dist<eps;
9547     }
9548   else
9549     {//only one is quadratic
9550       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9551       if(!status0)
9552         return false;
9553       const double *a(0),*bb(0),*be(0);
9554       if(typ1.isQuadratic())
9555         {
9556           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9557         }
9558       else
9559         {
9560           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9561         }
9562       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9563       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9564       return dist<eps;
9565     }
9566 }
9567
9568 /*!
9569  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9570  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9571  *
9572  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9573  */
9574 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9575 {
9576   if(candidatesIn2DEnd==candidatesIn2DBg)
9577     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9578   const double *coo(mesh2DSplit->getCoords()->begin());
9579   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9580     return *candidatesIn2DBg;
9581   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9582   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9583   if(cellIdInMesh1DSplitRelative<0)
9584     cur1D->changeOrientationOfCells();
9585   const int *c1D(cur1D->getNodalConnectivity()->begin());
9586   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9587   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9588     {
9589       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9590       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9591       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9592       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9593       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9594       for(unsigned it2=0;it2<sz;it2++)
9595         {
9596           INTERP_KERNEL::NormalizedCellType typeOfSon;
9597           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9598           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9599           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9600             return *it;
9601         }
9602     }
9603   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9604 }
9605
9606 /// @endcond
9607
9608 /*!
9609  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9610  * 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
9611  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9612  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9613  *
9614  * \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
9615  *                      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)
9616  * \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
9617  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9618  * \param [in] eps - precision used to perform intersections and localization operations.
9619  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9620  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9621  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9622  *                               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.
9623  * \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
9624  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9625  *                               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.
9626  *
9627  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9628  */
9629 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9630 {
9631   if(!mesh2D || !mesh1D)
9632     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9633   mesh2D->checkFullyDefined();
9634   mesh1D->checkFullyDefined();
9635   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9636   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9637     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9638   // Step 1: compute all edge intersections (new nodes)
9639   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9640   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9641   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9642   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9643   //
9644   // Build desc connectivity
9645   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9646   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9647   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9648   std::map<int,int> mergedNodes;
9649   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9650   // use mergeNodes to fix intersectEdge1
9651   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9652     {
9653       std::size_t n((*it0).size()/2);
9654       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9655       std::map<int,int>::const_iterator it1;
9656       it1=mergedNodes.find(eltStart);
9657       if(it1!=mergedNodes.end())
9658         (*it0)[0]=(*it1).second;
9659       it1=mergedNodes.find(eltEnd);
9660       if(it1!=mergedNodes.end())
9661         (*it0)[2*n-1]=(*it1).second;
9662     }
9663   //
9664   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9665   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9666   // Step 2: re-order newly created nodes according to the ordering found in m2
9667   std::vector< std::vector<int> > intersectEdge2;
9668   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9669   subDiv2.clear();
9670   // Step 3: compute splitMesh1D
9671   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9672   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9673   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9674       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9675   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9676   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9677   // deal with cells in mesh2D that are not cut but only some of their edges are
9678   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9679   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9680   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9681   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s;//ids in mesh2D that are impacted by the fact that some edges of \a mesh1D are part of the edges of those cells
9682   if(!idsInDesc2DToBeRefined->empty())
9683     {
9684       DataArrayInt *out0(0),*outi0(0);
9685       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9686       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9687       out0s=out0;
9688       out0s=out0s->buildUnique();
9689       out0s->sort(true);
9690     }
9691   //
9692   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9693   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9694   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9695   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9696   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9697   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9698   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9699     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9700   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9701   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9702   if((DataArrayInt *)out0s)
9703     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9704   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9705   // OK all is ready to insert in ret2 mesh
9706   if(!untouchedCells->empty())
9707     {// the most easy part, cells in mesh2D not impacted at all
9708       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9709       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9710       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9711     }
9712   if((DataArrayInt *)out0s)
9713     {// here dealing with cells in out0s but not in cellsToBeModified
9714       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9715       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9716       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9717         {
9718           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9719           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9720         }
9721       int offset(ret2->getNumberOfTuples());
9722       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9723       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9724       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9725       int kk(0),*ret3ptr(partOfRet3->getPointer());
9726       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9727         {
9728           int faceId(std::abs(*it)-1);
9729           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9730             {
9731               int tmp(fewModifiedCells->locateValue(*it2));
9732               if(tmp!=-1)
9733                 {
9734                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9735                     ret3ptr[2*kk]=tmp+offset;
9736                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9737                     ret3ptr[2*kk+1]=tmp+offset;
9738                 }
9739               else
9740                 {//the current edge is shared by a 2D cell that will be split just after
9741                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9742                     ret3ptr[2*kk]=-(*it2+1);
9743                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9744                     ret3ptr[2*kk+1]=-(*it2+1);
9745                 }
9746             }
9747         }
9748       m1Desc->setCoords(ret1->getCoords());
9749       ret1NonCol->setCoords(ret1->getCoords());
9750       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9751       if(!outMesh2DSplit.empty())
9752         {
9753           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9754           for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9755             (*itt)->setCoords(da);
9756         }
9757     }
9758   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9759   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9760     {
9761       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9762       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9763       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9764       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9765       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9766       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> splitOfOneCell(BuildMesh2DCutFrom(eps,*it,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3));
9767       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9768       outMesh2DSplit.push_back(splitOfOneCell);
9769       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9770         ret2->pushBackSilent(*it);
9771     }
9772   //
9773   std::size_t nbOfMeshes(outMesh2DSplit.size());
9774   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9775   for(std::size_t i=0;i<nbOfMeshes;i++)
9776     tmp[i]=outMesh2DSplit[i];
9777   //
9778   ret1->getCoords()->setInfoOnComponents(compNames);
9779   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9780   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9781   ret3->rearrange(1);
9782   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9783   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9784     {
9785       int old2DCellId(-ret3->getIJ(*it,0)-1);
9786       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9787       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
9788     }
9789   ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9790   ret3->rearrange(2);
9791   //
9792   splitMesh1D=ret1.retn();
9793   splitMesh2D=ret2D.retn();
9794   cellIdInMesh2D=ret2.retn();
9795   cellIdInMesh1D=ret3.retn();
9796 }
9797
9798 /**
9799  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9800  * (newly created) nodes corresponding to the edge intersections.
9801  * Output params:
9802  * @param[out] cr, crI connectivity of the resulting mesh
9803  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9804  * TODO: describe input parameters
9805  */
9806 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9807                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9808                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9809                                                          const std::vector<double>& addCoords,
9810                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9811 {
9812   static const int SPACEDIM=2;
9813   const double *coo1(m1->getCoords()->getConstPointer());
9814   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9815   int offset1(m1->getNumberOfNodes());
9816   const double *coo2(m2->getCoords()->getConstPointer());
9817   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9818   int offset2(offset1+m2->getNumberOfNodes());
9819   int offset3(offset2+((int)addCoords.size())/2);
9820   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9821   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9822   // Here a BBTree on 2D-cells, not on segments:
9823   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9824   int ncell1(m1->getNumberOfCells());
9825   crI.push_back(0);
9826   for(int i=0;i<ncell1;i++)
9827     {
9828       std::vector<int> candidates2;
9829       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9830       std::map<INTERP_KERNEL::Node *,int> mapp;
9831       std::map<int,INTERP_KERNEL::Node *> mappRev;
9832       INTERP_KERNEL::QuadraticPolygon pol1;
9833       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9834       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9835       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9836       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9837       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9838       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9839           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9840       //
9841       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
9842       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9843       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9844       for(it1.first();!it1.finished();it1.next())
9845         edges1.insert(it1.current()->getPtr());
9846       //
9847       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9848       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9849       int ii=0;
9850       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9851         {
9852           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9853           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9854           // Complete mapping with elements coming from the current cell it2 in mesh2:
9855           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9856           // pol2 is the new QP in the final merged result.
9857           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9858               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9859         }
9860       ii=0;
9861       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9862         {
9863           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9864           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9865           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9866           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9867         }
9868       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9869       // by m2 but that we still want to keep in the final result.
9870       if(!edges1.empty())
9871         {
9872           try
9873           {
9874               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9875           }
9876           catch(INTERP_KERNEL::Exception& e)
9877           {
9878               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();
9879               throw INTERP_KERNEL::Exception(oss.str().c_str());
9880           }
9881         }
9882       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9883         (*it).second->decrRef();
9884     }
9885 }
9886
9887 /**
9888  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9889  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9890  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
9891  * The caller is to deal with the resulting DataArrayInt.
9892  *  \throw If the coordinate array is not set.
9893  *  \throw If the nodal connectivity of the cells is not defined.
9894  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9895  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9896  *
9897  * \sa DataArrayInt::sortEachPairToMakeALinkedList
9898  */
9899 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9900 {
9901   checkFullyDefined();
9902   if(getMeshDimension()!=1)
9903     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
9904
9905   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9906   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9907   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9908   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9909   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9910   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9911   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9912   const int * dsi(_dsi->getConstPointer());
9913   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9914   m_points=0;
9915   if (dsii->getNumberOfTuples())
9916     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9917
9918   int nc(getNumberOfCells());
9919   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
9920   result->alloc(nc,1);
9921
9922   // set of edges not used so far
9923   std::set<int> edgeSet;
9924   for (int i=0; i<nc; edgeSet.insert(i), i++);
9925
9926   int startSeg=0;
9927   int newIdx=0;
9928   // while we have points with only one neighbor segments
9929   do
9930     {
9931       std::list<int> linePiece;
9932       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
9933       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
9934         {
9935           // Fill the list forward (resp. backward) from the start segment:
9936           int activeSeg = startSeg;
9937           int prevPointId = -20;
9938           int ptId;
9939           while (!edgeSet.empty())
9940             {
9941               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
9942                 {
9943                   if (direction==0)
9944                     linePiece.push_back(activeSeg);
9945                   else
9946                     linePiece.push_front(activeSeg);
9947                   edgeSet.erase(activeSeg);
9948                 }
9949
9950               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
9951               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
9952               if (dsi[ptId] == 1) // hitting the end of the line
9953                 break;
9954               prevPointId = ptId;
9955               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
9956               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
9957             }
9958         }
9959       // Done, save final piece into DA:
9960       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
9961       newIdx += linePiece.size();
9962
9963       // identify next valid start segment (one which is not consumed)
9964       if(!edgeSet.empty())
9965         startSeg = *(edgeSet.begin());
9966     }
9967   while (!edgeSet.empty());
9968   return result.retn();
9969 }
9970
9971 /// @cond INTERNAL
9972
9973 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9974 {
9975   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
9976   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
9977   if(it==m.end())
9978     throw INTERP_KERNEL::Exception("Internal error in remapping !");
9979   int v((*it).second);
9980   if(v==forbVal0 || v==forbVal1)
9981     return ;
9982   if(std::find(isect.begin(),isect.end(),v)==isect.end())
9983     isect.push_back(v);
9984 }
9985
9986 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
9987 {
9988   int sz(c.size());
9989   if(sz<=1)
9990     return false;
9991   bool presenceOfOn(false);
9992   for(int i=0;i<sz;i++)
9993     {
9994       INTERP_KERNEL::ElementaryEdge *e(c[i]);
9995       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
9996         continue ;
9997       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
9998       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
9999     }
10000   return presenceOfOn;
10001 }
10002
10003 /// @endcond
10004
10005 /**
10006  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg and in \a subNodesInSegI using index storage mode.
10007  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if a minimal creation of new nodes is wanted.
10008  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add nodes if a SEG3 is split without information of middle.
10009  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
10010  *
10011  * \return int - the number of new nodes created (in most of cases 0).
10012  * 
10013  * \throw If \a this is not coherent.
10014  * \throw If \a this has not spaceDim equal to 2.
10015  * \throw If \a this has not meshDim equal to 2.
10016  * \throw If some subcells needed to be split are orphan.
10017  * \sa MEDCouplingUMesh::conformize2D
10018  */
10019 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10020 {
10021   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10022     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10023   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10024   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10025     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10026   if(midOpt==0 && midOptI==0)
10027     {
10028       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10029       return 0;
10030     }
10031   else if(midOpt!=0 && midOptI!=0)
10032     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10033   else
10034     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10035 }
10036
10037 /*!
10038  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10039  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10040  * 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
10041  * 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).
10042  * 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.
10043  * 
10044  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10045  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10046  *
10047  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10048  * This method expects that all nodes in \a this are not closer than \a eps.
10049  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10050  * 
10051  * \param [in] eps the relative error to detect merged edges.
10052  * \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
10053  *                           that the user is expected to deal with.
10054  *
10055  * \throw If \a this is not coherent.
10056  * \throw If \a this has not spaceDim equal to 2.
10057  * \throw If \a this has not meshDim equal to 2.
10058  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10059  */
10060 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10061 {
10062   static const int SPACEDIM=2;
10063   checkCoherency();
10064   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10065     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10066   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10067   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10068   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10069   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10070   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10071   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10072   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10073   std::vector<double> addCoo;
10074   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10075   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10076   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10077   for(int i=0;i<nDescCell;i++)
10078     {
10079       std::vector<int> candidates;
10080       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10081       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10082         if(*it>i)
10083           {
10084             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10085             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10086                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10087             INTERP_KERNEL::MergePoints merge;
10088             INTERP_KERNEL::QuadraticPolygon c1,c2;
10089             e1->intersectWith(e2,merge,c1,c2);
10090             e1->decrRef(); e2->decrRef();
10091             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10092               overlapEdge[i].push_back(*it);
10093             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10094               overlapEdge[*it].push_back(i);
10095           }
10096     }
10097   // splitting done. sort intersect point in intersectEdge.
10098   std::vector< std::vector<int> > middle(nDescCell);
10099   int nbOf2DCellsToBeSplit(0);
10100   bool middleNeedsToBeUsed(false);
10101   std::vector<bool> cells2DToTreat(nDescCell,false);
10102   for(int i=0;i<nDescCell;i++)
10103     {
10104       std::vector<int>& isect(intersectEdge[i]);
10105       int sz((int)isect.size());
10106       if(sz>1)
10107         {
10108           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10109           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10110           e->sortSubNodesAbs(coords,isect);
10111           e->decrRef();
10112         }
10113       if(sz!=0)
10114         {
10115           int idx0(rdi[i]),idx1(rdi[i+1]);
10116           if(idx1-idx0!=1)
10117             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10118           if(!cells2DToTreat[rd[idx0]])
10119             {
10120               cells2DToTreat[rd[idx0]]=true;
10121               nbOf2DCellsToBeSplit++;
10122             }
10123           // try to reuse at most eventual 'middle' of SEG3
10124           std::vector<int>& mid(middle[i]);
10125           mid.resize(sz+1,-1);
10126           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10127             {
10128               middleNeedsToBeUsed=true;
10129               const std::vector<int>& candidates(overlapEdge[i]);
10130               std::vector<int> trueCandidates;
10131               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10132                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10133                   trueCandidates.push_back(*itc);
10134               int stNode(c[ci[i]+1]),endNode(isect[0]);
10135               for(int j=0;j<sz+1;j++)
10136                 {
10137                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10138                     {
10139                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10140                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10141                         { mid[j]=*itc; break; }
10142                     }
10143                   stNode=endNode;
10144                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10145                 }
10146             }
10147         }
10148     }
10149   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10150   if(nbOf2DCellsToBeSplit==0)
10151     return ret.retn();
10152   //
10153   int *retPtr(ret->getPointer());
10154   for(int i=0;i<nCell;i++)
10155     if(cells2DToTreat[i])
10156       *retPtr++=i;
10157   //
10158   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10159   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10160   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10161   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10162   if(middleNeedsToBeUsed)
10163     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10164   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10165   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10166   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.
10167   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10168   {
10169     bool areNodesMerged; int newNbOfNodes;
10170     if(nbOfNodesCreated!=0)
10171       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10172   }
10173   return ret.retn();
10174 }
10175
10176 /*!
10177  * 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.
10178  * 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).
10179  * 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
10180  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10181  * 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
10182  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10183  *
10184  * 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
10185  * using new instance, idem for coordinates.
10186  *
10187  * 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.
10188  * 
10189  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10190  *
10191  * \throw If \a this is not coherent.
10192  * \throw If \a this has not spaceDim equal to 2.
10193  * \throw If \a this has not meshDim equal to 2.
10194  * 
10195  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10196  */
10197 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10198 {
10199   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10200   checkCoherency();
10201   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10202     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10203   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10204   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10205   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10206   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10207   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10208   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10209   const double *coords(_coords->begin());
10210   int *newciptr(newci->getPointer());
10211   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10212     {
10213       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10214         ret->pushBackSilent(i);
10215       newciptr[1]=newc->getNumberOfTuples();
10216     }
10217   //
10218   if(ret->empty())
10219     return ret.retn();
10220   if(!appendedCoords->empty())
10221     {
10222       appendedCoords->rearrange(2);
10223       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10224       //non const part
10225       setCoords(newCoords);
10226     }
10227   //non const part
10228   setConnectivity(newc,newci,true);
10229   return ret.retn();
10230 }
10231
10232 /*!
10233  * \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.
10234  *                               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.
10235  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10236  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10237  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10238  * \param [out] addCoo - nodes to be append at the end
10239  * \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.
10240  */
10241 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10242                                          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)
10243 {
10244   static const int SPACEDIM=2;
10245   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10246   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10247   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10248   // Build BB tree of all edges in the tool mesh (second mesh)
10249   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10250   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10251   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10252   intersectEdge1.resize(nDescCell1);
10253   colinear2.resize(nDescCell2);
10254   subDiv2.resize(nDescCell2);
10255   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10256
10257   std::vector<int> candidates1(1);
10258   int offset1(m1Desc->getNumberOfNodes());
10259   int offset2(offset1+m2Desc->getNumberOfNodes());
10260   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10261     {
10262       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10263       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10264       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10265         {
10266           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10267           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10268           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10269           candidates1[0]=i;
10270           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10271           // 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
10272           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10273           std::set<INTERP_KERNEL::Node *> nodes;
10274           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10275           std::size_t szz(nodes.size());
10276           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10277           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10278           for(std::size_t iii=0;iii<szz;iii++,itt++)
10279             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10280           // end of protection
10281           // Performs egde cutting:
10282           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10283           delete pol2;
10284           delete pol1;
10285         }
10286       else
10287         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10288         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10289     }
10290 }
10291
10292 /*!
10293  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10294  * It builds the descending connectivity of the two meshes, and then using a binary tree
10295  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10296  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10297  */
10298 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10299                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10300                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10301                                                    std::vector<double>& addCoo,
10302                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10303 {
10304   // Build desc connectivity
10305   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10306   desc2=DataArrayInt::New();
10307   descIndx2=DataArrayInt::New();
10308   revDesc2=DataArrayInt::New();
10309   revDescIndx2=DataArrayInt::New();
10310   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10311   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10312   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10313   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10314   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10315   std::map<int,int> notUsedMap;
10316   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10317   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10318   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10319 }
10320
10321 /*!
10322  * This method performs the 2nd step of Partition of 2D mesh.
10323  * This method has 4 inputs :
10324  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10325  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10326  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10327  * 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'
10328  * Nodes end up lying consecutively on a cutted edge.
10329  * \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.
10330  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10331  * \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.
10332  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10333  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10334  */
10335 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10336                                            const std::vector<double>& addCoo,
10337                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10338 {
10339   int offset1=m1->getNumberOfNodes();
10340   int ncell=m2->getNumberOfCells();
10341   const int *c=m2->getNodalConnectivity()->getConstPointer();
10342   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10343   const double *coo=m2->getCoords()->getConstPointer();
10344   const double *cooBis=m1->getCoords()->getConstPointer();
10345   int offset2=offset1+m2->getNumberOfNodes();
10346   intersectEdge.resize(ncell);
10347   for(int i=0;i<ncell;i++,cI++)
10348     {
10349       const std::vector<int>& divs=subDiv[i];
10350       int nnode=cI[1]-cI[0]-1;
10351       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10352       std::map<INTERP_KERNEL::Node *, int> mapp22;
10353       for(int j=0;j<nnode;j++)
10354         {
10355           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10356           int nnid=c[(*cI)+j+1];
10357           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10358           mapp22[nn]=nnid+offset1;
10359         }
10360       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10361       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10362         ((*it).second.first)->decrRef();
10363       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10364       std::map<INTERP_KERNEL::Node *,int> mapp3;
10365       for(std::size_t j=0;j<divs.size();j++)
10366         {
10367           int id=divs[j];
10368           INTERP_KERNEL::Node *tmp=0;
10369           if(id<offset1)
10370             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10371           else if(id<offset2)
10372             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10373           else
10374             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10375           addNodes[j]=tmp;
10376           mapp3[tmp]=id;
10377         }
10378       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10379       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10380         (*it)->decrRef();
10381       e->decrRef();
10382     }
10383 }
10384
10385 /*!
10386  * 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).
10387  * 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
10388  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10389  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10390  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10391  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10392  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10393  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10394  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10395  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10396  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10397  * \param [out] cut3DSuf input/output param.
10398  */
10399 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10400                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10401                                                    const int *desc, const int *descIndx, 
10402                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10403 {
10404   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10405   int nbOf3DSurfCell=(int)cut3DSurf.size();
10406   for(int i=0;i<nbOf3DSurfCell;i++)
10407     {
10408       std::vector<int> res;
10409       int offset=descIndx[i];
10410       int nbOfSeg=descIndx[i+1]-offset;
10411       for(int j=0;j<nbOfSeg;j++)
10412         {
10413           int edgeId=desc[offset+j];
10414           int status=cut3DCurve[edgeId];
10415           if(status!=-2)
10416             {
10417               if(status>-1)
10418                 res.push_back(status);
10419               else
10420                 {
10421                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10422                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10423                 }
10424             }
10425         }
10426       switch(res.size())
10427       {
10428         case 2:
10429           {
10430             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10431             break;
10432           }
10433         case 1:
10434         case 0:
10435           {
10436             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10437             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10438             if(res.size()==2)
10439               {
10440                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10441               }
10442             else
10443               {
10444                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10445               }
10446             break;
10447           }
10448         default:
10449           {// case when plane is on a multi colinear edge of a polyhedron
10450             if((int)res.size()==2*nbOfSeg)
10451               {
10452                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10453               }
10454             else
10455               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10456           }
10457       }
10458     }
10459 }
10460
10461 /*!
10462  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10463  * 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).
10464  * 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
10465  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10466  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10467  * \param desc is the descending connectivity 3D->3DSurf
10468  * \param descIndx is the descending connectivity index 3D->3DSurf
10469  */
10470 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10471                                                   const int *desc, const int *descIndx,
10472                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10473 {
10474   checkFullyDefined();
10475   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10476     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10477   const int *nodal3D=_nodal_connec->getConstPointer();
10478   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10479   int nbOfCells=getNumberOfCells();
10480   for(int i=0;i<nbOfCells;i++)
10481     {
10482       std::map<int, std::set<int> > m;
10483       int offset=descIndx[i];
10484       int nbOfFaces=descIndx[i+1]-offset;
10485       int start=-1;
10486       int end=-1;
10487       for(int j=0;j<nbOfFaces;j++)
10488         {
10489           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10490           if(p.first!=-1 && p.second!=-1)
10491             {
10492               if(p.first!=-2)
10493                 {
10494                   start=p.first; end=p.second;
10495                   m[p.first].insert(p.second);
10496                   m[p.second].insert(p.first);
10497                 }
10498               else
10499                 {
10500                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10501                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10502                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10503                   INTERP_KERNEL::NormalizedCellType cmsId;
10504                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10505                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10506                   for(unsigned k=0;k<nbOfNodesSon;k++)
10507                     {
10508                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10509                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10510                     }
10511                 }
10512             }
10513         }
10514       if(m.empty())
10515         continue;
10516       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10517       int prev=end;
10518       while(end!=start)
10519         {
10520           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10521           const std::set<int>& s=(*it).second;
10522           std::set<int> s2; s2.insert(prev);
10523           std::set<int> s3;
10524           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10525           if(s3.size()==1)
10526             {
10527               int val=*s3.begin();
10528               conn.push_back(start);
10529               prev=start;
10530               start=val;
10531             }
10532           else
10533             start=end;
10534         }
10535       conn.push_back(end);
10536       if(conn.size()>3)
10537         {
10538           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10539           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10540           cellIds->pushBackSilent(i);
10541         }
10542     }
10543 }
10544
10545 /*!
10546  * 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
10547  * 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
10548  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10549  * 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
10550  * 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.
10551  * 
10552  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10553  */
10554 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10555 {
10556   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10557   if(sz>=4)
10558     {
10559       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10560       if(cm.getDimension()==2)
10561         {
10562           const int *node=nodalConnBg+1;
10563           int startNode=*node++;
10564           double refX=coords[2*startNode];
10565           for(;node!=nodalConnEnd;node++)
10566             {
10567               if(coords[2*(*node)]<refX)
10568                 {
10569                   startNode=*node;
10570                   refX=coords[2*startNode];
10571                 }
10572             }
10573           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10574           refX=1e300;
10575           double tmp1;
10576           double tmp2[2];
10577           double angle0=-M_PI/2;
10578           //
10579           int nextNode=-1;
10580           int prevNode=-1;
10581           double resRef;
10582           double angleNext=0.;
10583           while(nextNode!=startNode)
10584             {
10585               nextNode=-1;
10586               resRef=1e300;
10587               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10588                 {
10589                   if(*node!=tmpOut.back() && *node!=prevNode)
10590                     {
10591                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10592                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10593                       double res;
10594                       if(angleM<=angle0)
10595                         res=angle0-angleM;
10596                       else
10597                         res=angle0-angleM+2.*M_PI;
10598                       if(res<resRef)
10599                         {
10600                           nextNode=*node;
10601                           resRef=res;
10602                           angleNext=angleM;
10603                         }
10604                     }
10605                 }
10606               if(nextNode!=startNode)
10607                 {
10608                   angle0=angleNext-M_PI;
10609                   if(angle0<-M_PI)
10610                     angle0+=2*M_PI;
10611                   prevNode=tmpOut.back();
10612                   tmpOut.push_back(nextNode);
10613                 }
10614             }
10615           std::vector<int> tmp3(2*(sz-1));
10616           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10617           std::copy(nodalConnBg+1,nodalConnEnd,it);
10618           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10619             {
10620               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10621               return false;
10622             }
10623           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10624             {
10625               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10626               return false;
10627             }
10628           else
10629             {
10630               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10631               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10632               return true;
10633             }
10634         }
10635       else
10636         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10637     }
10638   else
10639     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10640 }
10641
10642 /*!
10643  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10644  * 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.
10645  * 
10646  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10647  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10648  * \param [in,out] arr array in which the remove operation will be done.
10649  * \param [in,out] arrIndx array in the remove operation will modify
10650  * \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])
10651  * \return true if \b arr and \b arrIndx have been modified, false if not.
10652  */
10653 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10654 {
10655   if(!arrIndx || !arr)
10656     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10657   if(offsetForRemoval<0)
10658     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10659   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10660   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10661   int *arrIPtr=arrIndx->getPointer();
10662   *arrIPtr++=0;
10663   int previousArrI=0;
10664   const int *arrPtr=arr->getConstPointer();
10665   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10666   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10667     {
10668       if(*arrIPtr-previousArrI>offsetForRemoval)
10669         {
10670           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10671             {
10672               if(s.find(*work)==s.end())
10673                 arrOut.push_back(*work);
10674             }
10675         }
10676       previousArrI=*arrIPtr;
10677       *arrIPtr=(int)arrOut.size();
10678     }
10679   if(arr->getNumberOfTuples()==(int)arrOut.size())
10680     return false;
10681   arr->alloc((int)arrOut.size(),1);
10682   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10683   return true;
10684 }
10685
10686 /*!
10687  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10688  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10689  * The selection of extraction is done standardly in new2old format.
10690  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10691  *
10692  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10693  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10694  * \param [in] arrIn arr origin array from which the extraction will be done.
10695  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10696  * \param [out] arrOut the resulting array
10697  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10698  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10699  */
10700 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10701                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10702 {
10703   if(!arrIn || !arrIndxIn)
10704     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10705   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10706   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10707     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10708   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10709   const int *arrInPtr=arrIn->getConstPointer();
10710   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10711   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10712   if(nbOfGrps<0)
10713     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10714   int maxSizeOfArr=arrIn->getNumberOfTuples();
10715   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10716   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10717   arrIo->alloc((int)(sz+1),1);
10718   const int *idsIt=idsOfSelectBg;
10719   int *work=arrIo->getPointer();
10720   *work++=0;
10721   int lgth=0;
10722   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10723     {
10724       if(*idsIt>=0 && *idsIt<nbOfGrps)
10725         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10726       else
10727         {
10728           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10729           throw INTERP_KERNEL::Exception(oss.str().c_str());
10730         }
10731       if(lgth>=work[-1])
10732         *work=lgth;
10733       else
10734         {
10735           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10736           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10737           throw INTERP_KERNEL::Exception(oss.str().c_str());
10738         }
10739     }
10740   arro->alloc(lgth,1);
10741   work=arro->getPointer();
10742   idsIt=idsOfSelectBg;
10743   for(std::size_t i=0;i<sz;i++,idsIt++)
10744     {
10745       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10746         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10747       else
10748         {
10749           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10750           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10751           throw INTERP_KERNEL::Exception(oss.str().c_str());
10752         }
10753     }
10754   arrOut=arro.retn();
10755   arrIndexOut=arrIo.retn();
10756 }
10757
10758 /*!
10759  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10760  * 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 ).
10761  * The selection of extraction is done standardly in new2old format.
10762  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10763  *
10764  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10765  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10766  * \param [in] arrIn arr origin array from which the extraction will be done.
10767  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10768  * \param [out] arrOut the resulting array
10769  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10770  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10771  */
10772 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10773                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10774 {
10775   if(!arrIn || !arrIndxIn)
10776     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10777   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10778   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10779     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10780   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10781   const int *arrInPtr=arrIn->getConstPointer();
10782   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10783   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10784   if(nbOfGrps<0)
10785     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10786   int maxSizeOfArr=arrIn->getNumberOfTuples();
10787   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10788   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10789   arrIo->alloc((int)(sz+1),1);
10790   int idsIt=idsOfSelectStart;
10791   int *work=arrIo->getPointer();
10792   *work++=0;
10793   int lgth=0;
10794   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10795     {
10796       if(idsIt>=0 && idsIt<nbOfGrps)
10797         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10798       else
10799         {
10800           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10801           throw INTERP_KERNEL::Exception(oss.str().c_str());
10802         }
10803       if(lgth>=work[-1])
10804         *work=lgth;
10805       else
10806         {
10807           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10808           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10809           throw INTERP_KERNEL::Exception(oss.str().c_str());
10810         }
10811     }
10812   arro->alloc(lgth,1);
10813   work=arro->getPointer();
10814   idsIt=idsOfSelectStart;
10815   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10816     {
10817       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10818         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10819       else
10820         {
10821           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10822           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10823           throw INTERP_KERNEL::Exception(oss.str().c_str());
10824         }
10825     }
10826   arrOut=arro.retn();
10827   arrIndexOut=arrIo.retn();
10828 }
10829
10830 /*!
10831  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10832  * 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
10833  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10834  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10835  *
10836  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10837  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10838  * \param [in] arrIn arr origin array from which the extraction will be done.
10839  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10840  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10841  * \param [in] srcArrIndex index array of \b srcArr
10842  * \param [out] arrOut the resulting array
10843  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10844  * 
10845  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10846  */
10847 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10848                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10849                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10850 {
10851   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10852     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10853   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10854   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10855   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10856   std::vector<bool> v(nbOfTuples,true);
10857   int offset=0;
10858   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10859   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10860   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10861     {
10862       if(*it>=0 && *it<nbOfTuples)
10863         {
10864           v[*it]=false;
10865           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10866         }
10867       else
10868         {
10869           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10870           throw INTERP_KERNEL::Exception(oss.str().c_str());
10871         }
10872     }
10873   srcArrIndexPtr=srcArrIndex->getConstPointer();
10874   arrIo->alloc(nbOfTuples+1,1);
10875   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10876   const int *arrInPtr=arrIn->getConstPointer();
10877   const int *srcArrPtr=srcArr->getConstPointer();
10878   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10879   int *arroPtr=arro->getPointer();
10880   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10881     {
10882       if(v[ii])
10883         {
10884           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10885           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10886         }
10887       else
10888         {
10889           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10890           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10891           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10892         }
10893     }
10894   arrOut=arro.retn();
10895   arrIndexOut=arrIo.retn();
10896 }
10897
10898 /*!
10899  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10900  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10901  *
10902  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10903  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10904  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10905  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10906  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10907  * \param [in] srcArrIndex index array of \b srcArr
10908  * 
10909  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10910  */
10911 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10912                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10913 {
10914   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10915     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10916   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10917   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10918   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10919   int *arrInOutPtr=arrInOut->getPointer();
10920   const int *srcArrPtr=srcArr->getConstPointer();
10921   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10922     {
10923       if(*it>=0 && *it<nbOfTuples)
10924         {
10925           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
10926             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
10927           else
10928             {
10929               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] !";
10930               throw INTERP_KERNEL::Exception(oss.str().c_str());
10931             }
10932         }
10933       else
10934         {
10935           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10936           throw INTERP_KERNEL::Exception(oss.str().c_str());
10937         }
10938     }
10939 }
10940
10941 /*!
10942  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10943  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10944  * 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]].
10945  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10946  * A negative value in \b arrIn means that it is ignored.
10947  * 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.
10948  * 
10949  * \param [in] arrIn arr origin array from which the extraction will be done.
10950  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10951  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10952  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
10953  */
10954 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
10955 {
10956   int seed=0,nbOfDepthPeelingPerformed=0;
10957   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
10958 }
10959
10960 /*!
10961  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
10962  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
10963  * 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]].
10964  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
10965  * A negative value in \b arrIn means that it is ignored.
10966  * 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.
10967  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
10968  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
10969  * \param [in] arrIn arr origin array from which the extraction will be done.
10970  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10971  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
10972  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
10973  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
10974  * \sa MEDCouplingUMesh::partitionBySpreadZone
10975  */
10976 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10977 {
10978   nbOfDepthPeelingPerformed=0;
10979   if(!arrIndxIn)
10980     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
10981   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10982   if(nbOfTuples<=0)
10983     {
10984       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
10985       return ret;
10986     }
10987   //
10988   std::vector<bool> fetched(nbOfTuples,false);
10989   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
10990 }
10991
10992 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
10993 {
10994   nbOfDepthPeelingPerformed=0;
10995   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
10996     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
10997   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10998   std::vector<bool> fetched2(nbOfTuples,false);
10999   int i=0;
11000   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11001     {
11002       if(*seedElt>=0 && *seedElt<nbOfTuples)
11003         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11004       else
11005         { std::ostringstream oss; oss << "MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : At pos #" << i << " of seeds value is " << *seedElt << "! Should be in [0," << nbOfTuples << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
11006     }
11007   const int *arrInPtr=arrIn->getConstPointer();
11008   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11009   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11010   std::vector<int> idsToFetch1(seedBg,seedEnd);
11011   std::vector<int> idsToFetch2;
11012   std::vector<int> *idsToFetch=&idsToFetch1;
11013   std::vector<int> *idsToFetchOther=&idsToFetch2;
11014   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11015     {
11016       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11017         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11018           if(!fetched[*it2])
11019             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11020       std::swap(idsToFetch,idsToFetchOther);
11021       idsToFetchOther->clear();
11022       nbOfDepthPeelingPerformed++;
11023     }
11024   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11025   i=0;
11026   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11027   int *retPtr=ret->getPointer();
11028   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11029     if(*it)
11030       *retPtr++=i;
11031   return ret.retn();
11032 }
11033
11034 /*!
11035  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11036  * 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
11037  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11038  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11039  *
11040  * \param [in] start begin of set of ids of the input extraction (included)
11041  * \param [in] end end of set of ids of the input extraction (excluded)
11042  * \param [in] step step of the set of ids in range mode.
11043  * \param [in] arrIn arr origin array from which the extraction will be done.
11044  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11045  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11046  * \param [in] srcArrIndex index array of \b srcArr
11047  * \param [out] arrOut the resulting array
11048  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11049  * 
11050  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11051  */
11052 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11053                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11054                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11055 {
11056   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11057     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11058   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11059   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11060   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11061   int offset=0;
11062   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11063   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11064   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11065   int it=start;
11066   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11067     {
11068       if(it>=0 && it<nbOfTuples)
11069         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11070       else
11071         {
11072           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11073           throw INTERP_KERNEL::Exception(oss.str().c_str());
11074         }
11075     }
11076   srcArrIndexPtr=srcArrIndex->getConstPointer();
11077   arrIo->alloc(nbOfTuples+1,1);
11078   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11079   const int *arrInPtr=arrIn->getConstPointer();
11080   const int *srcArrPtr=srcArr->getConstPointer();
11081   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11082   int *arroPtr=arro->getPointer();
11083   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11084     {
11085       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11086       if(pos<0)
11087         {
11088           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11089           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11090         }
11091       else
11092         {
11093           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11094           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11095         }
11096     }
11097   arrOut=arro.retn();
11098   arrIndexOut=arrIo.retn();
11099 }
11100
11101 /*!
11102  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11103  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11104  *
11105  * \param [in] start begin of set of ids of the input extraction (included)
11106  * \param [in] end end of set of ids of the input extraction (excluded)
11107  * \param [in] step step of the set of ids in range mode.
11108  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11109  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11110  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11111  * \param [in] srcArrIndex index array of \b srcArr
11112  * 
11113  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11114  */
11115 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11116                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11117 {
11118   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11119     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11120   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11121   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11122   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11123   int *arrInOutPtr=arrInOut->getPointer();
11124   const int *srcArrPtr=srcArr->getConstPointer();
11125   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11126   int it=start;
11127   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11128     {
11129       if(it>=0 && it<nbOfTuples)
11130         {
11131           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11132             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11133           else
11134             {
11135               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11136               throw INTERP_KERNEL::Exception(oss.str().c_str());
11137             }
11138         }
11139       else
11140         {
11141           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11142           throw INTERP_KERNEL::Exception(oss.str().c_str());
11143         }
11144     }
11145 }
11146
11147 /*!
11148  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11149  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11150  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11151  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11152  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11153  * 
11154  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11155  */
11156 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11157 {
11158   checkFullyDefined();
11159   int mdim=getMeshDimension();
11160   int spaceDim=getSpaceDimension();
11161   if(mdim!=spaceDim)
11162     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11163   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11164   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11165   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11166   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11167   ret->setCoords(getCoords());
11168   ret->allocateCells((int)partition.size());
11169   //
11170   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11171     {
11172       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11173       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11174       switch(mdim)
11175       {
11176         case 2:
11177           cell=tmp->buildUnionOf2DMesh();
11178           break;
11179         case 3:
11180           cell=tmp->buildUnionOf3DMesh();
11181           break;
11182         default:
11183           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11184       }
11185
11186       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11187     }
11188   //
11189   ret->finishInsertingCells();
11190   return ret.retn();
11191 }
11192
11193 /*!
11194  * This method partitions \b this into contiguous zone.
11195  * This method only needs a well defined connectivity. Coordinates are not considered here.
11196  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11197  */
11198 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11199 {
11200   int nbOfCellsCur=getNumberOfCells();
11201   std::vector<DataArrayInt *> ret;
11202   if(nbOfCellsCur<=0)
11203     return ret;
11204   DataArrayInt *neigh=0,*neighI=0;
11205   computeNeighborsOfCells(neigh,neighI);
11206   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11207   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11208   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11209   int seed=0;
11210   while(seed<nbOfCellsCur)
11211     {
11212       int nbOfPeelPerformed=0;
11213       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11214       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11215     }
11216   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11217     ret.push_back((*it).retn());
11218   return ret;
11219 }
11220
11221 /*!
11222  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11223  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11224  *
11225  * \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.
11226  * \return a newly allocated DataArrayInt to be managed by the caller.
11227  * \throw In case of \a code has not the right format (typically of size 3*n)
11228  */
11229 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11230 {
11231   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11232   std::size_t nb=code.size()/3;
11233   if(code.size()%3!=0)
11234     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11235   ret->alloc((int)nb,2);
11236   int *retPtr=ret->getPointer();
11237   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11238     {
11239       retPtr[0]=code[3*i+2];
11240       retPtr[1]=code[3*i+2]+code[3*i+1];
11241     }
11242   return ret.retn();
11243 }
11244
11245 /*!
11246  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11247  * All cells in \a this are expected to be linear 3D cells.
11248  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11249  * It leads to an increase to number of cells.
11250  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11251  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11252  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11253  *
11254  * \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.
11255  *                      For all other cells, the splitting policy will be ignored.
11256  * \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. 
11257  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11258  *          an id of old cell producing it. The caller is to delete this array using
11259  *         decrRef() as it is no more needed.
11260  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11261  *
11262  * \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
11263  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11264  * 
11265  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11266  * \throw If \a this is not fully constituted with linear 3D cells.
11267  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11268  */
11269 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11270 {
11271   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11272   checkConnectivityFullyDefined();
11273   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11274     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11275   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11276   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11278   int *retPt(ret->getPointer());
11279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11280   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11281   const int *oldc(_nodal_connec->begin());
11282   const int *oldci(_nodal_connec_index->begin());
11283   const double *coords(_coords->begin());
11284   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11285     {
11286       std::vector<int> a; std::vector<double> b;
11287       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11288       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11289       const int *aa(&a[0]);
11290       if(!b.empty())
11291         {
11292           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11293             if(*it<0)
11294               *it=(-(*(it))-1+nbNodes);
11295           addPts->insertAtTheEnd(b.begin(),b.end());
11296           nbNodes+=(int)b.size()/3;
11297         }
11298       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11299         newConn->insertAtTheEnd(aa,aa+4);
11300     }
11301   if(!addPts->empty())
11302     {
11303       addPts->rearrange(3);
11304       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11305       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11306       ret0->setCoords(addPts);
11307     }
11308   else
11309     {
11310       nbOfAdditionalPoints=0;
11311       ret0->setCoords(getCoords());
11312     }
11313   ret0->setNodalConnectivity(newConn);
11314   //
11315   ret->computeOffsets2();
11316   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11317   return ret0.retn();
11318 }
11319
11320 /*!
11321  * 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). 
11322  *
11323  * \sa MEDCouplingUMesh::split2DCells
11324  */
11325 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11326 {
11327   checkConnectivityFullyDefined();
11328   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11329   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11330   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11331   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11332   int prevPosOfCi(ciPtr[0]);
11333   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11334     {
11335       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11336       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11337       for(int j=0;j<sz;j++)
11338         {
11339           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11340           for(int k=0;k<sz2;k++)
11341             *cPtr++=subPtr[offset2+k];
11342           if(j!=sz-1)
11343             *cPtr++=oldConn[prevPosOfCi+j+2];
11344           deltaSz+=sz2;
11345         }
11346       prevPosOfCi=ciPtr[1];
11347       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11348     }
11349   if(c->end()!=cPtr)
11350     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11351   _nodal_connec->decrRef();
11352   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11353 }
11354
11355 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11356 {
11357   if(id!=-1)
11358     return id;
11359   else
11360     {
11361       int ret(nodesCnter++);
11362       double newPt[2];
11363       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11364       addCoo.insertAtTheEnd(newPt,newPt+2);
11365       return ret;
11366     }
11367 }
11368
11369 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11370 {
11371   if(id!=-1)
11372     return id;
11373   else
11374     {
11375       int ret(nodesCnter++);
11376       double newPt[2];
11377       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11378       addCoo.insertAtTheEnd(newPt,newPt+2);
11379       return ret;
11380     }
11381 }
11382
11383
11384 /// @cond INTERNAL
11385
11386 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)
11387 {
11388   int tmp[3];
11389   int trueStart(start>=0?start:nbOfEdges+start);
11390   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11391   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11392   if(linOrArc)
11393     {
11394       if(stp-start>1)
11395         {
11396           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11397           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11398           middles.push_back(tmp3+offset);
11399         }
11400       else
11401         middles.push_back(connBg[trueStart+nbOfEdges]);
11402     }
11403 }
11404
11405 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)
11406 {
11407   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11408   newConnOfCell->pushBackSilent(tmpEnd);
11409   if(linOrArc)
11410     {
11411       if(stp-start>1)
11412         {
11413           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11414           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11415           middles.push_back(tmp3+offset);
11416         }
11417       else
11418         middles.push_back(connBg[start+nbOfEdges]);
11419     }
11420 }
11421
11422 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)
11423 {
11424   // only the quadratic point to deal with:
11425   if(linOrArc)
11426     {
11427       if(stp-start>1)
11428         {
11429           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11430           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11431           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11432           middles.push_back(tmp3+offset);
11433         }
11434       else
11435         middles.push_back(connBg[start+nbOfEdges]);
11436     }
11437 }
11438
11439 /// @cond INTERNAL
11440
11441 /*!
11442  * 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 ) .
11443  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11444  */
11445 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11446 {
11447   std::size_t sz(std::distance(connBg,connEnd));
11448   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11449     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11450   sz--;
11451   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11452   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11453   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11454   unsigned nbOfHit(0); // number of fusions operated
11455   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11456   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
11457   INTERP_KERNEL::NormalizedCellType typeOfSon;
11458   std::vector<int> middles;
11459   bool ret(false);
11460   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11461     {
11462       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11463       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11464       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11465       posEndElt = posBaseElt+1;
11466
11467       // Look backward first: are the final edges of the cells colinear with the first ones?
11468       // This initializes posBaseElt.
11469       if(nbOfTurn==0)
11470         {
11471           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11472             {
11473               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11474               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11475               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11476               bool isColinear=eint->areColinears();
11477               if(isColinear)
11478                 {
11479                   nbOfHit++;
11480                   posBaseElt--;
11481                   ret=true;
11482                 }
11483               delete eint;
11484               eCand->decrRef();
11485               if(!isColinear)
11486                 break;
11487             }
11488         }
11489       // Now move forward:
11490       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11491       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11492         {
11493           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11494           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11495           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11496           bool isColinear(eint->areColinears());
11497           if(isColinear)
11498             {
11499               nbOfHit++;
11500               posEndElt++;
11501               ret=true;
11502             }
11503           delete eint;
11504           eCand->decrRef();
11505           if(!isColinear)
11506               break;
11507         }
11508       //push [posBaseElt,posEndElt) in newConnOfCell using e
11509       // 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!
11510       if(nbOfTurn==0)
11511         // at the begining of the connectivity (insert type)
11512         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11513       else if((nbOfHit+nbOfTurn) != (nbs-1))
11514         // in the middle
11515         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11516       if ((nbOfHit+nbOfTurn) == (nbs-1))
11517         // at the end (only quad points to deal with)
11518         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11519       posBaseElt=posEndElt;
11520       e->decrRef();
11521     }
11522   if(!middles.empty())
11523     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11524   return ret;
11525 }
11526
11527 /*!
11528  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11529  *
11530  * \return  int - the number of new nodes created.
11531  * \sa MEDCouplingUMesh::split2DCells
11532  */
11533 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11534 {
11535   checkCoherency();
11536   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11537   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11538   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11539   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11540   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11541   const double *oldCoordsPtr(getCoords()->begin());
11542   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11543   int prevPosOfCi(ciPtr[0]);
11544   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11545     {
11546       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11547       for(int j=0;j<sz;j++)
11548         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11549       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11550       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11551         {
11552           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11553           if(sz2==0)
11554             {
11555               if(j<sz-1)
11556                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11557               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11558               continue;
11559             }
11560           std::vector<INTERP_KERNEL::Node *> ns(3);
11561           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11562           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11563           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11564           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11565           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11566             {
11567               cPtr[1]=subPtr[offset2+k];
11568               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11569             }
11570           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11571           if(j!=sz-1)
11572             { cPtr[1]=tmpEnd; }
11573           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11574         }
11575       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11576       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11577     }
11578   if(c->end()!=cPtr)
11579     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11580   _nodal_connec->decrRef();
11581   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11582   addCoo->rearrange(2);
11583   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11584   setCoords(coo);
11585   return addCoo->getNumberOfTuples();
11586 }
11587
11588 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11589 {
11590   if(nodalConnec && nodalConnecIndex)
11591     {
11592       types.clear();
11593       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11594       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11595       if(nbOfElem>0)
11596         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11597           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11598     }
11599 }
11600
11601 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11602     _own_cell(true),_cell_id(-1),_nb_cell(0)
11603 {
11604   if(mesh)
11605     {
11606       mesh->incrRef();
11607       _nb_cell=mesh->getNumberOfCells();
11608     }
11609 }
11610
11611 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11612 {
11613   if(_mesh)
11614     _mesh->decrRef();
11615   if(_own_cell)
11616     delete _cell;
11617 }
11618
11619 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11620     _own_cell(false),_cell_id(bg-1),
11621     _nb_cell(end)
11622 {
11623   if(mesh)
11624     mesh->incrRef();
11625 }
11626
11627 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11628 {
11629   _cell_id++;
11630   if(_cell_id<_nb_cell)
11631     {
11632       _cell->next();
11633       return _cell;
11634     }
11635   else
11636     return 0;
11637 }
11638
11639 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11640 {
11641   if(_mesh)
11642     _mesh->incrRef();
11643 }
11644
11645 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11646 {
11647   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11648 }
11649
11650 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11651 {
11652   if(_mesh)
11653     _mesh->decrRef();
11654 }
11655
11656 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11657     _itc(itc),
11658     _bg(bg),_end(end)
11659 {
11660   if(_mesh)
11661     _mesh->incrRef();
11662 }
11663
11664 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11665 {
11666   if(_mesh)
11667     _mesh->decrRef();
11668 }
11669
11670 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11671 {
11672   return _type;
11673 }
11674
11675 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11676 {
11677   return _end-_bg;
11678 }
11679
11680 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11681 {
11682   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11683 }
11684
11685 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11686 {
11687   if(mesh)
11688     {
11689       mesh->incrRef();
11690       _nb_cell=mesh->getNumberOfCells();
11691     }
11692 }
11693
11694 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11695 {
11696   if(_mesh)
11697     _mesh->decrRef();
11698   delete _cell;
11699 }
11700
11701 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11702 {
11703   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11704   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11705   if(_cell_id<_nb_cell)
11706     {
11707       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11708       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11709       int startId=_cell_id;
11710       _cell_id+=nbOfElems;
11711       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11712     }
11713   else
11714     return 0;
11715 }
11716
11717 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11718 {
11719   if(mesh)
11720     {
11721       _conn=mesh->getNodalConnectivity()->getPointer();
11722       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11723     }
11724 }
11725
11726 void MEDCouplingUMeshCell::next()
11727 {
11728   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11729     {
11730       _conn+=_conn_lgth;
11731       _conn_indx++;
11732     }
11733   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11734 }
11735
11736 std::string MEDCouplingUMeshCell::repr() const
11737 {
11738   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11739     {
11740       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11741       oss << " : ";
11742       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11743       return oss.str();
11744     }
11745   else
11746     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11747 }
11748
11749 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11750 {
11751   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11752     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11753   else
11754     return INTERP_KERNEL::NORM_ERROR;
11755 }
11756
11757 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11758 {
11759   lgth=_conn_lgth;
11760   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11761     return _conn;
11762   else
11763     return 0;
11764 }