Salome HOME
extract medtool doc from MED
[modules/med.git] / medtool / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "MEDCouplingSkyLineArray.hxx"
26 #include "CellModel.hxx"
27 #include "VolSurfUser.txx"
28 #include "InterpolationUtils.hxx"
29 #include "PointLocatorAlgos.txx"
30 #include "BBTree.txx"
31 #include "BBTreeDst.txx"
32 #include "SplitterTetra.hxx"
33 #include "DiameterCalculator.hxx"
34 #include "DirectedBoundingBox.hxx"
35 #include "InterpKernelMatrixTools.hxx"
36 #include "InterpKernelMeshQuality.hxx"
37 #include "InterpKernelCellSimplify.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelAutoPtr.hxx"
40 #include "InterpKernelGeo2DNode.hxx"
41 #include "InterpKernelGeo2DEdgeLin.hxx"
42 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
43 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
44
45 #include <sstream>
46 #include <fstream>
47 #include <numeric>
48 #include <cstring>
49 #include <limits>
50 #include <list>
51
52 using namespace ParaMEDMEM;
53
54 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
55
56 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
57
58 MEDCouplingUMesh *MEDCouplingUMesh::New()
59 {
60   return new MEDCouplingUMesh;
61 }
62
63 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
64 {
65   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
66   ret->setName(meshName);
67   ret->setMeshDimension(meshDim);
68   return ret;
69 }
70
71 /*!
72  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
73  * between \a this and the new mesh.
74  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
75  *          delete this mesh using decrRef() as it is no more needed. 
76  */
77 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
78 {
79   return clone(true);
80 }
81
82 /*!
83  * Returns a new MEDCouplingMesh which is a copy of \a this one.
84  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
85  * this mesh are shared by the new mesh.
86  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
87  *          delete this mesh using decrRef() as it is no more needed. 
88  */
89 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
90 {
91   return new MEDCouplingUMesh(*this,recDeepCpy);
92 }
93
94 /*!
95  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
96  * The coordinates are shared between \a this and the returned instance.
97  * 
98  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
99  * \sa MEDCouplingUMesh::deepCpy
100  */
101 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
102 {
103   checkConnectivityFullyDefined();
104   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
105   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
106   ret->setConnectivity(c,ci);
107   return ret.retn();
108 }
109
110 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
111 {
112   if(!other)
113     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
114   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
115   if(!otherC)
116     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
117   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
118   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
119 }
120
121 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
122 {
123   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
124   return ret;
125 }
126
127 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
128 {
129   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
130   ret.push_back(_nodal_connec);
131   ret.push_back(_nodal_connec_index);
132   return ret;
133 }
134
135 void MEDCouplingUMesh::updateTime() const
136 {
137   MEDCouplingPointSet::updateTime();
138   if(_nodal_connec)
139     {
140       updateTimeWith(*_nodal_connec);
141     }
142   if(_nodal_connec_index)
143     {
144       updateTimeWith(*_nodal_connec_index);
145     }
146 }
147
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
149 {
150 }
151
152 /*!
153  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154  * then \a this mesh is most probably is writable, exchangeable and available for most
155  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156  * this method to check that all is in order with \a this mesh.
157  *  \throw If the mesh dimension is not set.
158  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
159  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160  *  \throw If the connectivity data array has more than one component.
161  *  \throw If the connectivity data array has a named component.
162  *  \throw If the connectivity index data array has more than one component.
163  *  \throw If the connectivity index data array has a named component.
164  */
165 void MEDCouplingUMesh::checkCoherency() const
166 {
167   if(_mesh_dim<-1)
168     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
169   if(_mesh_dim!=-1)
170     MEDCouplingPointSet::checkCoherency();
171   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
172     {
173       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
174         {
175           std::ostringstream message;
176           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177           throw INTERP_KERNEL::Exception(message.str().c_str());
178         }
179     }
180   if(_nodal_connec)
181     {
182       if(_nodal_connec->getNumberOfComponents()!=1)
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184       if(_nodal_connec->getInfoOnComponent(0)!="")
185         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
186     }
187   else
188     if(_mesh_dim!=-1)
189       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190   if(_nodal_connec_index)
191     {
192       if(_nodal_connec_index->getNumberOfComponents()!=1)
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194       if(_nodal_connec_index->getInfoOnComponent(0)!="")
195         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
196     }
197   else
198     if(_mesh_dim!=-1)
199       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
200 }
201
202 /*!
203  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204  * then \a this mesh is most probably is writable, exchangeable and available for all
205  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206  * method thoroughly checks the nodal connectivity.
207  *  \param [in] eps - a not used parameter.
208  *  \throw If the mesh dimension is not set.
209  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
210  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211  *  \throw If the connectivity data array has more than one component.
212  *  \throw If the connectivity data array has a named component.
213  *  \throw If the connectivity index data array has more than one component.
214  *  \throw If the connectivity index data array has a named component.
215  *  \throw If number of nodes defining an element does not correspond to the type of element.
216  *  \throw If the nodal connectivity includes an invalid node id.
217  */
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
219 {
220   checkCoherency();
221   if(_mesh_dim==-1)
222     return ;
223   int meshDim=getMeshDimension();
224   int nbOfNodes=getNumberOfNodes();
225   int nbOfCells=getNumberOfCells();
226   const int *ptr=_nodal_connec->getConstPointer();
227   const int *ptrI=_nodal_connec_index->getConstPointer();
228   for(int i=0;i<nbOfCells;i++)
229     {
230       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231       if((int)cm.getDimension()!=meshDim)
232         {
233           std::ostringstream oss;
234           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235           throw INTERP_KERNEL::Exception(oss.str().c_str());
236         }
237       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
238       if(!cm.isDynamic())
239         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
240           {
241             std::ostringstream oss;
242             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
243             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244             throw INTERP_KERNEL::Exception(oss.str().c_str());
245           }
246       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
247         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
248           {
249             std::ostringstream oss;
250             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
251             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
252             throw INTERP_KERNEL::Exception(oss.str().c_str());
253           }
254       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
255         {
256           int nodeId=*w;
257           if(nodeId>=0)
258             {
259               if(nodeId>=nbOfNodes)
260                 {
261                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
262                   throw INTERP_KERNEL::Exception(oss.str().c_str());
263                 }
264             }
265           else if(nodeId<-1)
266             {
267               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
268               throw INTERP_KERNEL::Exception(oss.str().c_str());
269             }
270           else
271             {
272               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
273                 {
274                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
275                   throw INTERP_KERNEL::Exception(oss.str().c_str());
276                 }
277             }
278         }
279     }
280 }
281
282
283 /*!
284  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
285  * then \a this mesh is most probably is writable, exchangeable and available for all
286  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
287  *  \param [in] eps - a not used parameter.
288  *  \throw If the mesh dimension is not set.
289  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
290  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
291  *  \throw If the connectivity data array has more than one component.
292  *  \throw If the connectivity data array has a named component.
293  *  \throw If the connectivity index data array has more than one component.
294  *  \throw If the connectivity index data array has a named component.
295  *  \throw If number of nodes defining an element does not correspond to the type of element.
296  *  \throw If the nodal connectivity includes an invalid node id.
297  */
298 void MEDCouplingUMesh::checkCoherency2(double eps) const
299 {
300   checkCoherency1(eps);
301 }
302
303 /*!
304  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
305  * elements contained in the mesh. For more info on the mesh dimension see
306  * \ref MEDCouplingUMeshPage.
307  *  \param [in] meshDim - a new mesh dimension.
308  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
309  */
310 void MEDCouplingUMesh::setMeshDimension(int meshDim)
311 {
312   if(meshDim<-1 || meshDim>3)
313     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
314   _mesh_dim=meshDim;
315   declareAsNew();
316 }
317
318 /*!
319  * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
320  * the less will the library need to reallocate memory. If the number of cells to be inserted is not known simply put 0 to this parameter.
321  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
322  *
323  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
324  *
325  *  \if ENABLE_EXAMPLES
326  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
327  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
328  *  \endif
329  */
330 void MEDCouplingUMesh::allocateCells(int nbOfCells)
331 {
332   if(nbOfCells<0)
333     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
334   if(_nodal_connec_index)
335     {
336       _nodal_connec_index->decrRef();
337     }
338   if(_nodal_connec)
339     {
340       _nodal_connec->decrRef();
341     }
342   _nodal_connec_index=DataArrayInt::New();
343   _nodal_connec_index->reserve(nbOfCells+1);
344   _nodal_connec_index->pushBackSilent(0);
345   _nodal_connec=DataArrayInt::New();
346   _nodal_connec->reserve(2*nbOfCells);
347   _types.clear();
348   declareAsNew();
349 }
350
351 /*!
352  * Appends a cell to the connectivity array. For deeper understanding what is
353  * happening see \ref MEDCouplingUMeshNodalConnectivity.
354  *  \param [in] type - type of cell to add.
355  *  \param [in] size - number of nodes constituting this cell.
356  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
357  * 
358  *  \if ENABLE_EXAMPLES
359  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
360  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
361  *  \endif
362  */
363 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
364 {
365   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
366   if(_nodal_connec_index==0)
367     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
368   if((int)cm.getDimension()==_mesh_dim)
369     {
370       if(!cm.isDynamic())
371         if(size!=(int)cm.getNumberOfNodes())
372           {
373             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
374             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
375             throw INTERP_KERNEL::Exception(oss.str().c_str());
376           }
377       int idx=_nodal_connec_index->back();
378       int val=idx+size+1;
379       _nodal_connec_index->pushBackSilent(val);
380       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
381       _types.insert(type);
382     }
383   else
384     {
385       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
386       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
387       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
388       throw INTERP_KERNEL::Exception(oss.str().c_str());
389     }
390 }
391
392 /*!
393  * Compacts data arrays to release unused memory. This method is to be called after
394  * finishing cell insertion using \a this->insertNextCell().
395  * 
396  *  \if ENABLE_EXAMPLES
397  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
398  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
399  *  \endif
400  */
401 void MEDCouplingUMesh::finishInsertingCells()
402 {
403   _nodal_connec->pack();
404   _nodal_connec_index->pack();
405   _nodal_connec->declareAsNew();
406   _nodal_connec_index->declareAsNew();
407   updateTime();
408 }
409
410 /*!
411  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
412  * Useful for python users.
413  */
414 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
415 {
416   return new MEDCouplingUMeshCellIterator(this);
417 }
418
419 /*!
420  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
421  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
422  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
423  * Useful for python users.
424  */
425 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
426 {
427   if(!checkConsecutiveCellTypes())
428     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
429   return new MEDCouplingUMeshCellByTypeEntry(this);
430 }
431
432 /*!
433  * Returns a set of all cell types available in \a this mesh.
434  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
435  * \warning this method does not throw any exception even if \a this is not defined.
436  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
437  */
438 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
439 {
440   return _types;
441 }
442
443 /*!
444  * This method returns the sorted list of geometric types in \a this.
445  * 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
446  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
447  *
448  * \throw if connectivity in \a this is not correctly defined.
449  *  
450  * \sa MEDCouplingMesh::getAllGeoTypes
451  */
452 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
453 {
454   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
455   checkConnectivityFullyDefined();
456   int nbOfCells(getNumberOfCells());
457   if(nbOfCells==0)
458     return ret;
459   if(getMeshLength()<1)
460     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
461   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
462   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
463   for(int i=1;i<nbOfCells;i++,ci++)
464     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
465       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
466   return ret;
467 }
468
469 /*!
470  * This method is a method that compares \a this and \a other.
471  * This method compares \b all attributes, even names and component names.
472  */
473 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
474 {
475   if(!other)
476     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
477   std::ostringstream oss; oss.precision(15);
478   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
479   if(!otherC)
480     {
481       reason="mesh given in input is not castable in MEDCouplingUMesh !";
482       return false;
483     }
484   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
485     return false;
486   if(_mesh_dim!=otherC->_mesh_dim)
487     {
488       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
489       reason=oss.str();
490       return false;
491     }
492   if(_types!=otherC->_types)
493     {
494       oss << "umesh geometric type mismatch :\nThis geometric types are :";
495       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
496         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
497       oss << "\nOther geometric types are :";
498       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
499         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
500       reason=oss.str();
501       return false;
502     }
503   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
504     if(_nodal_connec==0 || otherC->_nodal_connec==0)
505       {
506         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
507         return false;
508       }
509   if(_nodal_connec!=otherC->_nodal_connec)
510     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
511       {
512         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
513         return false;
514       }
515   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
516     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
517       {
518         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
519         return false;
520       }
521   if(_nodal_connec_index!=otherC->_nodal_connec_index)
522     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
523       {
524         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
525         return false;
526       }
527   return true;
528 }
529
530 /*!
531  * Checks if data arrays of this mesh (node coordinates, nodal
532  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
533  * not considered.
534  *  \param [in] other - the mesh to compare with.
535  *  \param [in] prec - precision value used to compare node coordinates.
536  *  \return bool - \a true if the two meshes are same.
537  */
538 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
539 {
540   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
541   if(!otherC)
542     return false;
543   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
544     return false;
545   if(_mesh_dim!=otherC->_mesh_dim)
546     return false;
547   if(_types!=otherC->_types)
548     return false;
549   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
550     if(_nodal_connec==0 || otherC->_nodal_connec==0)
551       return false;
552   if(_nodal_connec!=otherC->_nodal_connec)
553     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
554       return false;
555   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
556     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
557       return false;
558   if(_nodal_connec_index!=otherC->_nodal_connec_index)
559     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
560       return false;
561   return true;
562 }
563
564 /*!
565  * Checks if \a this and \a other meshes are geometrically equivalent with high
566  * probability, else an exception is thrown. The meshes are considered equivalent if
567  * (1) meshes contain the same number of nodes and the same number of elements of the
568  * same types (2) three cells of the two meshes (first, last and middle) are based
569  * on coincident nodes (with a specified precision).
570  *  \param [in] other - the mesh to compare with.
571  *  \param [in] prec - the precision used to compare nodes of the two meshes.
572  *  \throw If the two meshes do not match.
573  */
574 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
575 {
576   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
577   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
578   if(!otherC)
579     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
580 }
581
582 /*!
583  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
584  * cells each node belongs to.
585  * \warning For speed reasons, this method does not check if node ids in the nodal
586  *          connectivity correspond to the size of node coordinates array.
587  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
588  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
589  *        dividing cell ids in \a revNodal into groups each referring to one
590  *        node. Its every element (except the last one) is an index pointing to the
591  *         first id of a group of cells. For example cells sharing the node #1 are 
592  *        described by following range of indices: 
593  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
594  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
595  *        Number of cells sharing the *i*-th node is
596  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
597  * \throw If the coordinates array is not set.
598  * \throw If the nodal connectivity of cells is not defined.
599  * 
600  * \if ENABLE_EXAMPLES
601  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
602  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
603  * \endif
604  */
605 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
606 {
607   checkFullyDefined();
608   int nbOfNodes=getNumberOfNodes();
609   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
610   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
611   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
612   const int *conn=_nodal_connec->getConstPointer();
613   const int *connIndex=_nodal_connec_index->getConstPointer();
614   int nbOfCells=getNumberOfCells();
615   int nbOfEltsInRevNodal=0;
616   for(int eltId=0;eltId<nbOfCells;eltId++)
617     {
618       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
619       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
620       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
621         if(*iter>=0)//for polyhedrons
622           {
623             nbOfEltsInRevNodal++;
624             revNodalIndxPtr[(*iter)+1]++;
625           }
626     }
627   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
628   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
629   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
630   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
631   for(int eltId=0;eltId<nbOfCells;eltId++)
632     {
633       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
634       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
635       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
636         if(*iter>=0)//for polyhedrons
637           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
638     }
639 }
640
641 /// @cond INTERNAL
642
643 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
644 {
645   return id;
646 }
647
648 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
649 {
650   if(!compute)
651     return id+1;
652   else
653     {
654       if(cm.getOrientationStatus(nb,conn1,conn2))
655         return id+1;
656       else
657         return -(id+1);
658     }
659 }
660
661 class MinusOneSonsGenerator
662 {
663 public:
664   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
665   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
666   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
667   static const int DELTA=1;
668 private:
669   const INTERP_KERNEL::CellModel& _cm;
670 };
671
672 class MinusOneSonsGeneratorBiQuadratic
673 {
674 public:
675   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
676   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
677   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
678   static const int DELTA=1;
679 private:
680   const INTERP_KERNEL::CellModel& _cm;
681 };
682
683 class MinusTwoSonsGenerator
684 {
685 public:
686   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
687   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
688   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
689   static const int DELTA=2;
690 private:
691   const INTERP_KERNEL::CellModel& _cm;
692 };
693
694 /// @endcond
695
696 /*!
697  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
698  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
699  * describing correspondence between cells of \a this and the result meshes are
700  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
701  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
702  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
703  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
704  * \warning For speed reasons, this method does not check if node ids in the nodal
705  *          connectivity correspond to the size of node coordinates array.
706  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
707  *          to write this mesh to the MED file, its cells must be sorted using
708  *          sortCellsInMEDFileFrmt().
709  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
710  *         each cell of \a this mesh.
711  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
712  *        dividing cell ids in \a desc into groups each referring to one
713  *        cell of \a this mesh. Its every element (except the last one) is an index
714  *        pointing to the first id of a group of cells. For example cells of the
715  *        result mesh bounding the cell #1 of \a this mesh are described by following
716  *        range of indices:
717  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
718  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
719  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
720  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
721  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
722  *         by each cell of the result mesh.
723  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
724  *        in the result mesh,
725  *        dividing cell ids in \a revDesc into groups each referring to one
726  *        cell of the result mesh the same way as \a descIndx divides \a desc.
727  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
728  *        delete this mesh using decrRef() as it is no more needed.
729  *  \throw If the coordinates array is not set.
730  *  \throw If the nodal connectivity of cells is node defined.
731  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
732  *         revDescIndx == NULL.
733  * 
734  *  \if ENABLE_EXAMPLES
735  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
736  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
737  *  \endif
738  * \sa buildDescendingConnectivity2()
739  */
740 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
741 {
742   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
743 }
744
745 /*!
746  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
747  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
748  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
749  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
750  * \sa MEDCouplingUMesh::buildDescendingConnectivity
751  */
752 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
753 {
754   checkFullyDefined();
755   if(getMeshDimension()!=3)
756     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
757   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
758 }
759
760 /*!
761  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
762  * this->getMeshDimension(), that bound cells of \a this mesh. In
763  * addition arrays describing correspondence between cells of \a this and the result
764  * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
765  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
766  *  mesh. This method differs from buildDescendingConnectivity() in that apart
767  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
768  * result meshes. So a positive id means that order of nodes in corresponding cells
769  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
770  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
771  * i.e. cell ids are one-based.
772  * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
773  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
774  * \warning For speed reasons, this method does not check if node ids in the nodal
775  *          connectivity correspond to the size of node coordinates array.
776  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
777  *          to write this mesh to the MED file, its cells must be sorted using
778  *          sortCellsInMEDFileFrmt().
779  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
780  *         each cell of \a this mesh.
781  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
782  *        dividing cell ids in \a desc into groups each referring to one
783  *        cell of \a this mesh. Its every element (except the last one) is an index
784  *        pointing to the first id of a group of cells. For example cells of the
785  *        result mesh bounding the cell #1 of \a this mesh are described by following
786  *        range of indices:
787  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
788  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
789  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
790  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
791  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
792  *         by each cell of the result mesh.
793  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
794  *        in the result mesh,
795  *        dividing cell ids in \a revDesc into groups each referring to one
796  *        cell of the result mesh the same way as \a descIndx divides \a desc.
797  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
798  *        shares the node coordinates array with \a this mesh. The caller is to
799  *        delete this mesh using decrRef() as it is no more needed.
800  *  \throw If the coordinates array is not set.
801  *  \throw If the nodal connectivity of cells is node defined.
802  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
803  *         revDescIndx == NULL.
804  * 
805  *  \if ENABLE_EXAMPLES
806  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
807  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
808  *  \endif
809  * \sa buildDescendingConnectivity()
810  */
811 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
812 {
813   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
814 }
815
816 /*!
817  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
818  * For speed reasons no check of this will be done. This method calls
819  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
820  * This method lists cell by cell in \b this which are its neighbors. To compute the result
821  * only connectivities are considered.
822  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
823  * The format of return is hence \ref numbering-indirect.
824  *
825  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
826  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
827  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
828  * is equal to the last values in \b neighborsIndx.
829  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
830  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
831  */
832 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
833 {
834   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
835   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
836   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
837   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
838   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
839   meshDM1=0;
840   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
841 }
842
843 /*!
844  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
845  * of MEDCouplingUMesh::computeNeighborsOfCells.
846  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
847  * typically the case to extract a set a neighbours,
848  * excluding a set of meshdim-1 cells in input descending connectivity.
849  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
850  * the result of MEDCouplingUMesh::buildDescendingConnectivity.
851  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
852  * are considered.
853  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
854  *
855  * \param [in] desc descending connectivity array.
856  * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
857  * \param [in] revDesc reverse descending connectivity array.
858  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
859  * \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
860  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
861  * \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.
862  */
863 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
864                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
865 {
866   if(!desc || !descIndx || !revDesc || !revDescIndx)
867     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
868   const int *descPtr=desc->getConstPointer();
869   const int *descIPtr=descIndx->getConstPointer();
870   const int *revDescPtr=revDesc->getConstPointer();
871   const int *revDescIPtr=revDescIndx->getConstPointer();
872   //
873   int nbCells=descIndx->getNumberOfTuples()-1;
874   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
875   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
876   int *out1Ptr=out1->getPointer();
877   *out1Ptr++=0;
878   out0->reserve(desc->getNumberOfTuples());
879   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
880     {
881       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
882         {
883           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
884           s.erase(i);
885           out0->insertAtTheEnd(s.begin(),s.end());
886         }
887       *out1Ptr=out0->getNumberOfTuples();
888     }
889   neighbors=out0.retn();
890   neighborsIndx=out1.retn();
891 }
892
893 /*!
894  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
895  * For speed reasons no check of this will be done. This method calls
896  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
897  * This method lists node by node in \b this which are its neighbors. To compute the result
898  * only connectivities are considered.
899  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
900  *
901  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
902  * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
903  * parameter allows to select the right part in this array (\ref numbering-indirect).
904  * The number of tuples is equal to the last values in \b neighborsIndx.
905  * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
906  * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
907  */
908 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
909 {
910   checkFullyDefined();
911   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
912   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
913   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
914   switch(mdim)
915   {
916     case 3:
917       {
918         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
919         break;
920       }
921     case 2:
922       {
923         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
924         break;
925       }
926     case 1:
927       {
928         mesh1D=const_cast<MEDCouplingUMesh *>(this);
929         mesh1D->incrRef();
930         break;
931       }
932     default:
933       {
934         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
935       }
936   }
937   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
938   mesh1D->getReverseNodalConnectivity(desc,descIndx);
939   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
940   ret0->alloc(desc->getNumberOfTuples(),1);
941   int *r0Pt(ret0->getPointer());
942   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
943   for(int i=0;i<nbNodes;i++,rni++)
944     {
945       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
946         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
947     }
948   neighbors=ret0.retn();
949   neighborsIdx=descIndx.retn();
950 }
951
952 /// @cond INTERNAL
953
954 /*!
955  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
956  * For speed reasons no check of this will be done.
957  */
958 template<class SonsGenerator>
959 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
960 {
961   if(!desc || !descIndx || !revDesc || !revDescIndx)
962     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
963   checkConnectivityFullyDefined();
964   int nbOfCells=getNumberOfCells();
965   int nbOfNodes=getNumberOfNodes();
966   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
967   int *revNodalIndxPtr=revNodalIndx->getPointer();
968   const int *conn=_nodal_connec->getConstPointer();
969   const int *connIndex=_nodal_connec_index->getConstPointer();
970   std::string name="Mesh constituent of "; name+=getName();
971   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
972   ret->setCoords(getCoords());
973   ret->allocateCells(2*nbOfCells);
974   descIndx->alloc(nbOfCells+1,1);
975   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
976   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
977   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
978     {
979       int pos=connIndex[eltId];
980       int posP1=connIndex[eltId+1];
981       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
982       SonsGenerator sg(cm);
983       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
984       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
985       for(unsigned i=0;i<nbOfSons;i++)
986         {
987           INTERP_KERNEL::NormalizedCellType cmsId;
988           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
989           for(unsigned k=0;k<nbOfNodesSon;k++)
990             if(tmp[k]>=0)
991               revNodalIndxPtr[tmp[k]+1]++;
992           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
993           revDesc2->pushBackSilent(eltId);
994         }
995       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
996     }
997   int nbOfCellsM1=ret->getNumberOfCells();
998   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
999   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
1000   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
1001   int *revNodalPtr=revNodal->getPointer();
1002   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
1003   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
1004   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
1005     {
1006       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
1007       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
1008       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
1009         if(*iter>=0)//for polyhedrons
1010           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
1011     }
1012   //
1013   DataArrayInt *commonCells=0,*commonCellsI=0;
1014   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
1015   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1016   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1017   int newNbOfCellsM1=-1;
1018   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
1019                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1020   std::vector<bool> isImpacted(nbOfCellsM1,false);
1021   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1022     for(int work2=work[0];work2!=work[1];work2++)
1023       isImpacted[commonCellsPtr[work2]]=true;
1024   const int *o2nM1Ptr=o2nM1->getConstPointer();
1025   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1026   const int *n2oM1Ptr=n2oM1->getConstPointer();
1027   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1028   ret2->copyTinyInfoFrom(this);
1029   desc->alloc(descIndx->back(),1);
1030   int *descPtr=desc->getPointer();
1031   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1032   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1033     {
1034       if(!isImpacted[i])
1035         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1036       else
1037         {
1038           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1039             {
1040               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1041               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1042             }
1043           else
1044             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1045         }
1046     }
1047   revDesc->reserve(newNbOfCellsM1);
1048   revDescIndx->alloc(newNbOfCellsM1+1,1);
1049   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1050   const int *revDesc2Ptr=revDesc2->getConstPointer();
1051   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1052     {
1053       int oldCellIdM1=n2oM1Ptr[i];
1054       if(!isImpacted[oldCellIdM1])
1055         {
1056           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1057           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1058         }
1059       else
1060         {
1061           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1062             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1063           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1064           commonCellsIPtr++;
1065         }
1066     }
1067   //
1068   return ret2.retn();
1069 }
1070
1071 struct MEDCouplingAccVisit
1072 {
1073   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1074   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1075   int _new_nb_of_nodes;
1076 };
1077
1078 /// @endcond
1079
1080 /*!
1081  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1082  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1083  * array of cell ids. Pay attention that after conversion all algorithms work slower
1084  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1085  * conversion due presence of invalid ids in the array of cells to convert, as a
1086  * result \a this mesh contains some already converted elements. In this case the 2D
1087  * mesh remains valid but 3D mesh becomes \b inconsistent!
1088  *  \warning This method can significantly modify the order of geometric types in \a this,
1089  *          hence, to write this mesh to the MED file, its cells must be sorted using
1090  *          sortCellsInMEDFileFrmt().
1091  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1092  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1093  *         cellIdsToConvertBg.
1094  *  \throw If the coordinates array is not set.
1095  *  \throw If the nodal connectivity of cells is node defined.
1096  *  \throw If dimension of \a this mesh is not either 2 or 3.
1097  *
1098  *  \if ENABLE_EXAMPLES
1099  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1100  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1101  *  \endif
1102  */
1103 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1104 {
1105   checkFullyDefined();
1106   int dim=getMeshDimension();
1107   if(dim<2 || dim>3)
1108     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1109   int nbOfCells(getNumberOfCells());
1110   if(dim==2)
1111     {
1112       const int *connIndex=_nodal_connec_index->getConstPointer();
1113       int *conn=_nodal_connec->getPointer();
1114       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1115         {
1116           if(*iter>=0 && *iter<nbOfCells)
1117             {
1118               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1119               if(!cm.isQuadratic())
1120                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1121               else
1122                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1123             }
1124           else
1125             {
1126               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1127               oss << " in range [0," << nbOfCells << ") !";
1128               throw INTERP_KERNEL::Exception(oss.str().c_str());
1129             }
1130         }
1131     }
1132   else
1133     {
1134       int *connIndex(_nodal_connec_index->getPointer());
1135       const int *connOld(_nodal_connec->getConstPointer());
1136       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1137       std::vector<bool> toBeDone(nbOfCells,false);
1138       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1139         {
1140           if(*iter>=0 && *iter<nbOfCells)
1141             toBeDone[*iter]=true;
1142           else
1143             {
1144               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1145               oss << " in range [0," << nbOfCells << ") !";
1146               throw INTERP_KERNEL::Exception(oss.str().c_str());
1147             }
1148         }
1149       for(int cellId=0;cellId<nbOfCells;cellId++)
1150         {
1151           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1152           int lgthOld(posP1-pos-1);
1153           if(toBeDone[cellId])
1154             {
1155               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1156               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1157               int *tmp(new int[nbOfFaces*lgthOld+1]);
1158               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1159               for(unsigned j=0;j<nbOfFaces;j++)
1160                 {
1161                   INTERP_KERNEL::NormalizedCellType type;
1162                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1163                   work+=offset;
1164                   *work++=-1;
1165                 }
1166               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1167               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1168               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1169               delete [] tmp;
1170             }
1171           else
1172             {
1173               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1174               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1175             }
1176         }
1177       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1178     }
1179   computeTypes();
1180 }
1181
1182 /*!
1183  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1184  * polyhedrons (if \a this is a 3D mesh).
1185  *  \warning As this method is purely for user-friendliness and no optimization is
1186  *          done to avoid construction of a useless vector, this method can be costly
1187  *          in memory.
1188  *  \throw If the coordinates array is not set.
1189  *  \throw If the nodal connectivity of cells is node defined.
1190  *  \throw If dimension of \a this mesh is not either 2 or 3.
1191  */
1192 void MEDCouplingUMesh::convertAllToPoly()
1193 {
1194   int nbOfCells=getNumberOfCells();
1195   std::vector<int> cellIds(nbOfCells);
1196   for(int i=0;i<nbOfCells;i++)
1197     cellIds[i]=i;
1198   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1199 }
1200
1201 /*!
1202  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1203  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1204  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1205  * base facet of the volume and the second half of nodes describes an opposite facet
1206  * having the same number of nodes as the base one. This method converts such
1207  * connectivity to a valid polyhedral format where connectivity of each facet is
1208  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1209  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1210  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1211  * a correct orientation of the first facet of a polyhedron, else orientation of a
1212  * corrected cell is reverse.<br>
1213  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1214  * it releases the user from boring description of polyhedra connectivity in the valid
1215  * format.
1216  *  \throw If \a this->getMeshDimension() != 3.
1217  *  \throw If \a this->getSpaceDimension() != 3.
1218  *  \throw If the nodal connectivity of cells is not defined.
1219  *  \throw If the coordinates array is not set.
1220  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1221  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1222  *
1223  *  \if ENABLE_EXAMPLES
1224  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1225  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1226  *  \endif
1227  */
1228 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1229 {
1230   checkFullyDefined();
1231   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1232     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1233   int nbOfCells=getNumberOfCells();
1234   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1235   newCi->alloc(nbOfCells+1,1);
1236   int *newci=newCi->getPointer();
1237   const int *ci=_nodal_connec_index->getConstPointer();
1238   const int *c=_nodal_connec->getConstPointer();
1239   newci[0]=0;
1240   for(int i=0;i<nbOfCells;i++)
1241     {
1242       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1243       if(type==INTERP_KERNEL::NORM_POLYHED)
1244         {
1245           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1246             {
1247               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1248               throw INTERP_KERNEL::Exception(oss.str().c_str());
1249             }
1250           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1251           if(n2%2!=0)
1252             {
1253               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 !";
1254               throw INTERP_KERNEL::Exception(oss.str().c_str());
1255             }
1256           int n1=(int)(n2/2);
1257           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)
1258         }
1259       else
1260         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1261     }
1262   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1263   newC->alloc(newci[nbOfCells],1);
1264   int *newc=newC->getPointer();
1265   for(int i=0;i<nbOfCells;i++)
1266     {
1267       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1268       if(type==INTERP_KERNEL::NORM_POLYHED)
1269         {
1270           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1271           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1272           *newc++=-1;
1273           for(std::size_t j=0;j<n1;j++)
1274             {
1275               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1276               newc[n1+5*j]=-1;
1277               newc[n1+5*j+1]=c[ci[i]+1+j];
1278               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1279               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1280               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1281             }
1282           newc+=n1*6;
1283         }
1284       else
1285         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1286     }
1287   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1288   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1289 }
1290
1291
1292 /*!
1293  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1294  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1295  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1296  *          to write this mesh to the MED file, its cells must be sorted using
1297  *          sortCellsInMEDFileFrmt().
1298  * \return \c true if at least one cell has been converted, \c false else. In the
1299  *         last case the nodal connectivity remains unchanged.
1300  * \throw If the coordinates array is not set.
1301  * \throw If the nodal connectivity of cells is not defined.
1302  * \throw If \a this->getMeshDimension() < 0.
1303  */
1304 bool MEDCouplingUMesh::unPolyze()
1305 {
1306   checkFullyDefined();
1307   int mdim=getMeshDimension();
1308   if(mdim<0)
1309     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1310   if(mdim<=1)
1311     return false;
1312   int nbOfCells=getNumberOfCells();
1313   if(nbOfCells<1)
1314     return false;
1315   int initMeshLgth=getMeshLength();
1316   int *conn=_nodal_connec->getPointer();
1317   int *index=_nodal_connec_index->getPointer();
1318   int posOfCurCell=0;
1319   int newPos=0;
1320   int lgthOfCurCell;
1321   bool ret=false;
1322   for(int i=0;i<nbOfCells;i++)
1323     {
1324       lgthOfCurCell=index[i+1]-posOfCurCell;
1325       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1326       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1327       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1328       int newLgth;
1329       if(cm.isDynamic())
1330         {
1331           switch(cm.getDimension())
1332           {
1333             case 2:
1334               {
1335                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1336                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1337                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1338                 break;
1339               }
1340             case 3:
1341               {
1342                 int nbOfFaces,lgthOfPolyhConn;
1343                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1344                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1345                 break;
1346               }
1347             case 1:
1348               {
1349                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1350                 break;
1351               }
1352           }
1353           ret=ret || (newType!=type);
1354           conn[newPos]=newType;
1355           newPos+=newLgth+1;
1356           posOfCurCell=index[i+1];
1357           index[i+1]=newPos;
1358         }
1359       else
1360         {
1361           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1362           newPos+=lgthOfCurCell;
1363           posOfCurCell+=lgthOfCurCell;
1364           index[i+1]=newPos;
1365         }
1366     }
1367   if(newPos!=initMeshLgth)
1368     _nodal_connec->reAlloc(newPos);
1369   if(ret)
1370     computeTypes();
1371   return ret;
1372 }
1373
1374 /*!
1375  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1376  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1377  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1378  *
1379  * \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 
1380  *             precision.
1381  */
1382 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1383 {
1384   checkFullyDefined();
1385   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1386     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1387   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1388   coords->recenterForMaxPrecision(eps);
1389   //
1390   int nbOfCells=getNumberOfCells();
1391   const int *conn=_nodal_connec->getConstPointer();
1392   const int *index=_nodal_connec_index->getConstPointer();
1393   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1394   connINew->alloc(nbOfCells+1,1);
1395   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1397   bool changed=false;
1398   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1399     {
1400       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1401         {
1402           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1403           changed=true;
1404         }
1405       else
1406         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1407       *connINewPtr=connNew->getNumberOfTuples();
1408     }
1409   if(changed)
1410     setConnectivity(connNew,connINew,false);
1411 }
1412
1413 /*!
1414  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1415  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1416  * the format of the returned DataArrayInt instance.
1417  * 
1418  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1419  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1420  */
1421 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1422 {
1423   checkConnectivityFullyDefined();
1424   int nbOfCells=getNumberOfCells();
1425   const int *connIndex=_nodal_connec_index->getConstPointer();
1426   const int *conn=_nodal_connec->getConstPointer();
1427   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1428   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1429   std::vector<bool> retS(maxElt,false);
1430   for(int i=0;i<nbOfCells;i++)
1431     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1432       if(conn[j]>=0)
1433         retS[conn[j]]=true;
1434   int sz=0;
1435   for(int i=0;i<maxElt;i++)
1436     if(retS[i])
1437       sz++;
1438   DataArrayInt *ret=DataArrayInt::New();
1439   ret->alloc(sz,1);
1440   int *retPtr=ret->getPointer();
1441   for(int i=0;i<maxElt;i++)
1442     if(retS[i])
1443       *retPtr++=i;
1444   return ret;
1445 }
1446
1447 /*!
1448  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1449  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1450  */
1451 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1452 {
1453   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1454   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1455   for(int i=0;i<nbOfCells;i++)
1456     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1457       if(conn[j]>=0)
1458         {
1459           if(conn[j]<nbOfNodes)
1460             nodeIdsInUse[conn[j]]=true;
1461           else
1462             {
1463               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1464               throw INTERP_KERNEL::Exception(oss.str().c_str());
1465             }
1466         }
1467 }
1468
1469 /*!
1470  * Finds nodes not used in any cell and returns an array giving a new id to every node
1471  * by excluding the unused nodes, for which the array holds -1. The result array is
1472  * a mapping in "Old to New" mode. 
1473  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1474  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1475  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1476  *          if the node is unused or a new id else. The caller is to delete this
1477  *          array using decrRef() as it is no more needed.  
1478  *  \throw If the coordinates array is not set.
1479  *  \throw If the nodal connectivity of cells is not defined.
1480  *  \throw If the nodal connectivity includes an invalid id.
1481  *
1482  *  \if ENABLE_EXAMPLES
1483  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1484  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1485  *  \endif
1486  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1487  */
1488 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1489 {
1490   nbrOfNodesInUse=-1;
1491   int nbOfNodes(getNumberOfNodes());
1492   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1493   ret->alloc(nbOfNodes,1);
1494   int *traducer=ret->getPointer();
1495   std::fill(traducer,traducer+nbOfNodes,-1);
1496   int nbOfCells=getNumberOfCells();
1497   const int *connIndex=_nodal_connec_index->getConstPointer();
1498   const int *conn=_nodal_connec->getConstPointer();
1499   for(int i=0;i<nbOfCells;i++)
1500     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1501       if(conn[j]>=0)
1502         {
1503           if(conn[j]<nbOfNodes)
1504             traducer[conn[j]]=1;
1505           else
1506             {
1507               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1508               throw INTERP_KERNEL::Exception(oss.str().c_str());
1509             }
1510         }
1511   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1512   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1513   return ret.retn();
1514 }
1515
1516 /*!
1517  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1518  * For each cell in \b this the number of nodes constituting cell is computed.
1519  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1520  * So for pohyhedrons some nodes can be counted several times in the returned result.
1521  * 
1522  * \return a newly allocated array
1523  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1524  */
1525 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1526 {
1527   checkConnectivityFullyDefined();
1528   int nbOfCells=getNumberOfCells();
1529   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1530   ret->alloc(nbOfCells,1);
1531   int *retPtr=ret->getPointer();
1532   const int *conn=getNodalConnectivity()->getConstPointer();
1533   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1534   for(int i=0;i<nbOfCells;i++,retPtr++)
1535     {
1536       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1537         *retPtr=connI[i+1]-connI[i]-1;
1538       else
1539         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1540     }
1541   return ret.retn();
1542 }
1543
1544 /*!
1545  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1546  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1547  *
1548  * \return DataArrayInt * - new object to be deallocated by the caller.
1549  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1550  */
1551 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1552 {
1553   checkConnectivityFullyDefined();
1554   int nbOfCells=getNumberOfCells();
1555   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1556   ret->alloc(nbOfCells,1);
1557   int *retPtr=ret->getPointer();
1558   const int *conn=getNodalConnectivity()->getConstPointer();
1559   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1560   for(int i=0;i<nbOfCells;i++,retPtr++)
1561     {
1562       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1563       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1564         *retPtr=(int)s.size();
1565       else
1566         {
1567           s.erase(-1);
1568           *retPtr=(int)s.size();
1569         }
1570     }
1571   return ret.retn();
1572 }
1573
1574 /*!
1575  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1576  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1577  * 
1578  * \return a newly allocated array
1579  */
1580 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1581 {
1582   checkConnectivityFullyDefined();
1583   int nbOfCells=getNumberOfCells();
1584   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1585   ret->alloc(nbOfCells,1);
1586   int *retPtr=ret->getPointer();
1587   const int *conn=getNodalConnectivity()->getConstPointer();
1588   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1589   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1590     {
1591       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1592       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1593     }
1594   return ret.retn();
1595 }
1596
1597 /*!
1598  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1599  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1600  * array mean that the corresponding old node is no more used. 
1601  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1602  *           this->getNumberOfNodes() before call of this method. The caller is to
1603  *           delete this array using decrRef() as it is no more needed. 
1604  *  \throw If the coordinates array is not set.
1605  *  \throw If the nodal connectivity of cells is not defined.
1606  *  \throw If the nodal connectivity includes an invalid id.
1607  *  \sa areAllNodesFetched
1608  *
1609  *  \if ENABLE_EXAMPLES
1610  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1611  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1612  *  \endif
1613  */
1614 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1615 {
1616   return MEDCouplingPointSet::zipCoordsTraducer();
1617 }
1618
1619 /*!
1620  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1621  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1622  */
1623 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1624 {
1625   switch(compType)
1626   {
1627     case 0:
1628       return AreCellsEqual0(conn,connI,cell1,cell2);
1629     case 1:
1630       return AreCellsEqual1(conn,connI,cell1,cell2);
1631     case 2:
1632       return AreCellsEqual2(conn,connI,cell1,cell2);
1633     case 3:
1634       return AreCellsEqual3(conn,connI,cell1,cell2);
1635     case 7:
1636       return AreCellsEqual7(conn,connI,cell1,cell2);
1637   }
1638   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1639 }
1640
1641 /*!
1642  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1643  */
1644 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1645 {
1646   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1647     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1648   return 0;
1649 }
1650
1651 /*!
1652  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1653  */
1654 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1655 {
1656   int sz=connI[cell1+1]-connI[cell1];
1657   if(sz==connI[cell2+1]-connI[cell2])
1658     {
1659       if(conn[connI[cell1]]==conn[connI[cell2]])
1660         {
1661           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1662           unsigned dim=cm.getDimension();
1663           if(dim!=3)
1664             {
1665               if(dim!=1)
1666                 {
1667                   int sz1=2*(sz-1);
1668                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1669                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1670                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1671                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1672                   return work!=tmp+sz1?1:0;
1673                 }
1674               else
1675                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1676             }
1677           else
1678             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1679         }
1680     }
1681   return 0;
1682 }
1683
1684 /*!
1685  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1686  */
1687 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1688 {
1689   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1690     {
1691       if(conn[connI[cell1]]==conn[connI[cell2]])
1692         {
1693           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1694           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1695           return s1==s2?1:0;
1696         }
1697     }
1698   return 0;
1699 }
1700
1701 /*!
1702  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1703  */
1704 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1705 {
1706   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1707     {
1708       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1709       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1710       return s1==s2?1:0;
1711     }
1712   return 0;
1713 }
1714
1715 /*!
1716  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1717  */
1718 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1719 {
1720   int sz=connI[cell1+1]-connI[cell1];
1721   if(sz==connI[cell2+1]-connI[cell2])
1722     {
1723       if(conn[connI[cell1]]==conn[connI[cell2]])
1724         {
1725           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1726           unsigned dim=cm.getDimension();
1727           if(dim!=3)
1728             {
1729               if(dim!=1)
1730                 {
1731                   int sz1=2*(sz-1);
1732                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1733                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1734                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1735                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1736                   if(work!=tmp+sz1)
1737                     return 1;
1738                   else
1739                     {
1740                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1741                       std::reverse_iterator<int *> it2((int *)tmp);
1742                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1743                         return 2;
1744                       else
1745                         return 0;
1746                     }
1747
1748                   return work!=tmp+sz1?1:0;
1749                 }
1750               else
1751                 {//case of SEG2 and SEG3
1752                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1753                     return 1;
1754                   if(!cm.isQuadratic())
1755                     {
1756                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1757                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1758                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1759                         return 2;
1760                       return 0;
1761                     }
1762                   else
1763                     {
1764                       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])
1765                         return 2;
1766                       return 0;
1767                     }
1768                 }
1769             }
1770           else
1771             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1772         }
1773     }
1774   return 0;
1775 }
1776
1777 /*!
1778  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1779  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1780  * and result remains unchanged.
1781  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1782  * If in 'candidates' pool -1 value is considered as an empty value.
1783  * WARNING this method returns only ONE set of result !
1784  */
1785 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1786 {
1787   if(candidates.size()<1)
1788     return false;
1789   bool ret=false;
1790   std::vector<int>::const_iterator iter=candidates.begin();
1791   int start=(*iter++);
1792   for(;iter!=candidates.end();iter++)
1793     {
1794       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1795       if(status!=0)
1796         {
1797           if(!ret)
1798             {
1799               result->pushBackSilent(start);
1800               ret=true;
1801             }
1802           if(status==1)
1803             result->pushBackSilent(*iter);
1804           else
1805             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1806         }
1807     }
1808   return ret;
1809 }
1810
1811 /*!
1812  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1813  * by \a compType.
1814  * This method keeps the coordiantes of \a this. This method is time consuming.
1815  *
1816  * \param [in] compType input specifying the technique used to compare cells each other.
1817  *   - 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.
1818  *   - 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)
1819  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1820  *   - 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
1821  * can be used for users not sensitive to orientation of cell
1822  * \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.
1823  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1824  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1825  * \return the correspondance array old to new in a newly allocated array.
1826  * 
1827  */
1828 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1829 {
1830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1831   getReverseNodalConnectivity(revNodal,revNodalI);
1832   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1833 }
1834
1835 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1836                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1837 {
1838   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1839   int nbOfCells=nodalI->getNumberOfTuples()-1;
1840   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1841   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1842   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1843   std::vector<bool> isFetched(nbOfCells,false);
1844   if(startCellId==0)
1845     {
1846       for(int i=0;i<nbOfCells;i++)
1847         {
1848           if(!isFetched[i])
1849             {
1850               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1851               std::vector<int> v,v2;
1852               if(connOfNode!=connPtr+connIPtr[i+1])
1853                 {
1854                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1855                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1856                   connOfNode++;
1857                 }
1858               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1859                 if(*connOfNode>=0)
1860                   {
1861                     v=v2;
1862                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1863                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1864                     v2.resize(std::distance(v2.begin(),it));
1865                   }
1866               if(v2.size()>1)
1867                 {
1868                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1869                     {
1870                       int pos=commonCellsI->back();
1871                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1872                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1873                         isFetched[*it]=true;
1874                     }
1875                 }
1876             }
1877         }
1878     }
1879   else
1880     {
1881       for(int i=startCellId;i<nbOfCells;i++)
1882         {
1883           if(!isFetched[i])
1884             {
1885               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1886               std::vector<int> v,v2;
1887               if(connOfNode!=connPtr+connIPtr[i+1])
1888                 {
1889                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1890                   connOfNode++;
1891                 }
1892               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1893                 if(*connOfNode>=0)
1894                   {
1895                     v=v2;
1896                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1897                     v2.resize(std::distance(v2.begin(),it));
1898                   }
1899               if(v2.size()>1)
1900                 {
1901                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1902                     {
1903                       int pos=commonCellsI->back();
1904                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1905                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1906                         isFetched[*it]=true;
1907                     }
1908                 }
1909             }
1910         }
1911     }
1912   commonCellsArr=commonCells.retn();
1913   commonCellsIArr=commonCellsI.retn();
1914 }
1915
1916 /*!
1917  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1918  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1919  * than \a other->getNumberOfCells() in the returned array means that there is no
1920  * corresponding cell in \a this mesh.
1921  * It is expected that \a this and \a other meshes share the same node coordinates
1922  * array, if it is not so an exception is thrown. 
1923  *  \param [in] other - the mesh to compare with.
1924  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1925  *         valid values [0,1,2], see zipConnectivityTraducer().
1926  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1927  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1928  *         values. The caller is to delete this array using
1929  *         decrRef() as it is no more needed.
1930  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1931  *         mesh.
1932  *
1933  *  \if ENABLE_EXAMPLES
1934  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1935  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1936  *  \endif
1937  *  \sa checkDeepEquivalOnSameNodesWith()
1938  *  \sa checkGeoEquivalWith()
1939  */
1940 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1941 {
1942   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1943   int nbOfCells=getNumberOfCells();
1944   static const int possibleCompType[]={0,1,2};
1945   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1946     {
1947       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1948       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1949       oss << " !";
1950       throw INTERP_KERNEL::Exception(oss.str().c_str());
1951     }
1952   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1953   arr=o2n->substr(nbOfCells);
1954   arr->setName(other->getName());
1955   int tmp;
1956   if(other->getNumberOfCells()==0)
1957     return true;
1958   return arr->getMaxValue(tmp)<nbOfCells;
1959 }
1960
1961 /*!
1962  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1963  * This method tries to determine if \b other is fully included in \b this.
1964  * The main difference is that this method is not expected to throw exception.
1965  * This method has two outputs :
1966  *
1967  * \param other other mesh
1968  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1969  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1970  */
1971 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1972 {
1973   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1974   DataArrayInt *commonCells=0,*commonCellsI=0;
1975   int thisNbCells=getNumberOfCells();
1976   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1977   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1978   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1979   int otherNbCells=other->getNumberOfCells();
1980   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1981   arr2->alloc(otherNbCells,1);
1982   arr2->fillWithZero();
1983   int *arr2Ptr=arr2->getPointer();
1984   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1985   for(int i=0;i<nbOfCommon;i++)
1986     {
1987       int start=commonCellsPtr[commonCellsIPtr[i]];
1988       if(start<thisNbCells)
1989         {
1990           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1991             {
1992               int sig=commonCellsPtr[j]>0?1:-1;
1993               int val=std::abs(commonCellsPtr[j])-1;
1994               if(val>=thisNbCells)
1995                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1996             }
1997         }
1998     }
1999   arr2->setName(other->getName());
2000   if(arr2->presenceOfValue(0))
2001     return false;
2002   arr=arr2.retn();
2003   return true;
2004 }
2005
2006 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
2007 {
2008   if(!other)
2009     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
2010   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
2011   if(!otherC)
2012     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
2013   std::vector<const MEDCouplingUMesh *> ms(2);
2014   ms[0]=this;
2015   ms[1]=otherC;
2016   return MergeUMeshesOnSameCoords(ms);
2017 }
2018
2019 /*!
2020  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2021  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2022  * cellIds is not given explicitely but by a range python like.
2023  * 
2024  * \param start
2025  * \param end
2026  * \param step
2027  * \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.
2028  * \return a newly allocated
2029  * 
2030  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2031  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2032  */
2033 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2034 {
2035   if(getMeshDimension()!=-1)
2036     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2037   else
2038     {
2039       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2040       if(newNbOfCells!=1)
2041         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2042       if(start!=0)
2043         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2044       incrRef();
2045       return const_cast<MEDCouplingUMesh *>(this);
2046     }
2047 }
2048
2049 /*!
2050  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2051  * The result mesh shares or not the node coordinates array with \a this mesh depending
2052  * on \a keepCoords parameter.
2053  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2054  *           to write this mesh to the MED file, its cells must be sorted using
2055  *           sortCellsInMEDFileFrmt().
2056  *  \param [in] begin - an array of cell ids to include to the new mesh.
2057  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2058  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2059  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2060  *         by calling zipCoords().
2061  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2062  *         to delete this mesh using decrRef() as it is no more needed. 
2063  *  \throw If the coordinates array is not set.
2064  *  \throw If the nodal connectivity of cells is not defined.
2065  *  \throw If any cell id in the array \a begin is not valid.
2066  *
2067  *  \if ENABLE_EXAMPLES
2068  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2069  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2070  *  \endif
2071  */
2072 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2073 {
2074   if(getMeshDimension()!=-1)
2075     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2076   else
2077     {
2078       if(end-begin!=1)
2079         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2080       if(begin[0]!=0)
2081         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2082       incrRef();
2083       return const_cast<MEDCouplingUMesh *>(this);
2084     }
2085 }
2086
2087 /*!
2088  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2089  *
2090  * 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.
2091  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2092  * The number of cells of \b this will remain the same with this method.
2093  *
2094  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
2095  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
2096  * \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 ).
2097  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2098  */
2099 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2100 {
2101   checkConnectivityFullyDefined();
2102   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2103   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2104     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2105   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2106     {
2107       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2108       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2109       throw INTERP_KERNEL::Exception(oss.str().c_str());
2110     }
2111   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2112   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2113     {
2114       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2115       throw INTERP_KERNEL::Exception(oss.str().c_str());
2116     }
2117   int nbOfCells=getNumberOfCells();
2118   bool easyAssign=true;
2119   const int *connI=_nodal_connec_index->getConstPointer();
2120   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2121   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2122     {
2123       if(*it>=0 && *it<nbOfCells)
2124         {
2125           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2126         }
2127       else
2128         {
2129           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2130           throw INTERP_KERNEL::Exception(oss.str().c_str());
2131         }
2132     }
2133   if(easyAssign)
2134     {
2135       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2136       computeTypes();
2137     }
2138   else
2139     {
2140       DataArrayInt *arrOut=0,*arrIOut=0;
2141       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2142                                                arrOut,arrIOut);
2143       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2144       setConnectivity(arrOut,arrIOut,true);
2145     }
2146 }
2147
2148 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2149 {
2150   checkConnectivityFullyDefined();
2151   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2152   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2153     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2154   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2155     {
2156       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2157       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2158       throw INTERP_KERNEL::Exception(oss.str().c_str());
2159     }
2160   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2161   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2162     {
2163       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2164       throw INTERP_KERNEL::Exception(oss.str().c_str());
2165     }
2166   int nbOfCells=getNumberOfCells();
2167   bool easyAssign=true;
2168   const int *connI=_nodal_connec_index->getConstPointer();
2169   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2170   int it=start;
2171   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2172     {
2173       if(it>=0 && it<nbOfCells)
2174         {
2175           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2176         }
2177       else
2178         {
2179           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2180           throw INTERP_KERNEL::Exception(oss.str().c_str());
2181         }
2182     }
2183   if(easyAssign)
2184     {
2185       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2186       computeTypes();
2187     }
2188   else
2189     {
2190       DataArrayInt *arrOut=0,*arrIOut=0;
2191       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2192                                                 arrOut,arrIOut);
2193       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2194       setConnectivity(arrOut,arrIOut,true);
2195     }
2196 }                      
2197
2198 /*!
2199  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2200  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2201  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2202  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2203  *
2204  * \param [in] begin input start of array of node ids.
2205  * \param [in] end input end of array of node ids.
2206  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2207  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2208  */
2209 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2210 {
2211   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2212   checkConnectivityFullyDefined();
2213   int tmp=-1;
2214   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2215   std::vector<bool> fastFinder(sz,false);
2216   for(const int *work=begin;work!=end;work++)
2217     if(*work>=0 && *work<sz)
2218       fastFinder[*work]=true;
2219   int nbOfCells=getNumberOfCells();
2220   const int *conn=getNodalConnectivity()->getConstPointer();
2221   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2222   for(int i=0;i<nbOfCells;i++)
2223     {
2224       int ref=0,nbOfHit=0;
2225       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2226         if(*work2>=0)
2227           {
2228             ref++;
2229             if(fastFinder[*work2])
2230               nbOfHit++;
2231           }
2232       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2233         cellIdsKept->pushBackSilent(i);
2234     }
2235   cellIdsKeptArr=cellIdsKept.retn();
2236 }
2237
2238 /*!
2239  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2240  * this->getMeshDimension(), that bound some cells of \a this mesh.
2241  * The cells of lower dimension to include to the result mesh are selected basing on
2242  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2243  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2244  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2245  * created mesh shares the node coordinates array with \a this mesh. 
2246  *  \param [in] begin - the array of node ids.
2247  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2248  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2249  *         array \a begin are added, else cells whose any node is in the
2250  *         array \a begin are added.
2251  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2252  *         to delete this mesh using decrRef() as it is no more needed. 
2253  *  \throw If the coordinates array is not set.
2254  *  \throw If the nodal connectivity of cells is not defined.
2255  *  \throw If any node id in \a begin is not valid.
2256  *
2257  *  \if ENABLE_EXAMPLES
2258  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2259  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2260  *  \endif
2261  */
2262 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2263 {
2264   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2265   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2266   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2267   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2268   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2269 }
2270
2271 /*!
2272  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2273  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2274  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2275  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2276  *         by calling zipCoords().
2277  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2278  *         to delete this mesh using decrRef() as it is no more needed. 
2279  *  \throw If the coordinates array is not set.
2280  *  \throw If the nodal connectivity of cells is not defined.
2281  *
2282  *  \if ENABLE_EXAMPLES
2283  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2284  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2285  *  \endif
2286  */
2287 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2288 {
2289   DataArrayInt *desc=DataArrayInt::New();
2290   DataArrayInt *descIndx=DataArrayInt::New();
2291   DataArrayInt *revDesc=DataArrayInt::New();
2292   DataArrayInt *revDescIndx=DataArrayInt::New();
2293   //
2294   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2295   revDesc->decrRef();
2296   desc->decrRef();
2297   descIndx->decrRef();
2298   int nbOfCells=meshDM1->getNumberOfCells();
2299   const int *revDescIndxC=revDescIndx->getConstPointer();
2300   std::vector<int> boundaryCells;
2301   for(int i=0;i<nbOfCells;i++)
2302     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2303       boundaryCells.push_back(i);
2304   revDescIndx->decrRef();
2305   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2306   return ret;
2307 }
2308
2309 /*!
2310  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2311  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2312  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2313  */
2314 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2315 {
2316   checkFullyDefined();
2317   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2318   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2321   //
2322   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2323   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2324   //
2325   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2326   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2327   const int *revDescPtr=revDesc->getConstPointer();
2328   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2329   int nbOfCells=getNumberOfCells();
2330   std::vector<bool> ret1(nbOfCells,false);
2331   int sz=0;
2332   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2333     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2334       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2335   //
2336   DataArrayInt *ret2=DataArrayInt::New();
2337   ret2->alloc(sz,1);
2338   int *ret2Ptr=ret2->getPointer();
2339   sz=0;
2340   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2341     if(*it)
2342       *ret2Ptr++=sz;
2343   ret2->setName("BoundaryCells");
2344   return ret2;
2345 }
2346
2347 /*!
2348  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2349  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2350  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2351  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2352  *
2353  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2354  * This method also returns the cells ids set s1 which contains the cell ids in \b this for which one of the dim-1 constituent
2355  * equals a cell in \b otherDimM1OnSameCoords.
2356  *
2357  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2358  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2359  *
2360  * \param [in] otherDimM1OnSameCoords
2361  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2362  * \param [out] cellIdsRk1 a newly allocated array containing the cell ids of s1 \b indexed into the \b cellIdsRk0 subset. To get the absolute ids of s1, simply invoke
2363  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2364  */
2365 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2366 {
2367   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2368     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2369   checkConnectivityFullyDefined();
2370   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2371   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2372     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2373   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2374   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2375   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2376   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2377   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2378   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2379   DataArrayInt *idsOtherInConsti=0;
2380   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2381   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2382   if(!b)
2383     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2384   std::set<int> s1;
2385   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2386     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2387   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2388   s1arr_renum1->sort();
2389   cellIdsRk0=s0arr.retn();
2390   //cellIdsRk1=s_renum1.retn();
2391   cellIdsRk1=s1arr_renum1.retn();
2392 }
2393
2394 /*!
2395  * 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
2396  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2397  * 
2398  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2399  */
2400 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2401 {
2402   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2403   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2405   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2406   //
2407   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2408   revDesc=0; desc=0; descIndx=0;
2409   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2410   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2411   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2412 }
2413
2414 /*!
2415  * Finds nodes lying on the boundary of \a this mesh.
2416  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2417  *          nodes. The caller is to delete this array using decrRef() as it is no
2418  *          more needed.
2419  *  \throw If the coordinates array is not set.
2420  *  \throw If the nodal connectivity of cells is node defined.
2421  *
2422  *  \if ENABLE_EXAMPLES
2423  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2424  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2425  *  \endif
2426  */
2427 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2428 {
2429   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2430   return skin->computeFetchedNodeIds();
2431 }
2432
2433 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2434 {
2435   incrRef();
2436   return const_cast<MEDCouplingUMesh *>(this);
2437 }
2438
2439 /*!
2440  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2441  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2442  * 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.
2443  * 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.
2444  * 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.
2445  *
2446  * \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
2447  *             parameter is altered during the call.
2448  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2449  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2450  * \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.
2451  *
2452  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2453  */
2454 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2455                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2456 {
2457   typedef MEDCouplingAutoRefCountObjectPtr<DataArrayInt> DAInt;
2458
2459   checkFullyDefined();
2460   otherDimM1OnSameCoords.checkFullyDefined();
2461   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2462     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2463   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2464     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2465   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2466   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2467   DAInt cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2468   DAInt s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2469   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2470   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2471   DAInt s1=m0Part->computeFetchedNodeIds();
2472   DAInt s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2473   DAInt s3=s2->buildSubstraction(s1);
2474   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2475   //
2476   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2477   int nCells2 = m0Part2->getNumberOfCells();
2478   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2479   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2480   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2481   DataArrayInt *tmp00=0,*tmp11=0;
2482   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2483   DAInt neighInit00(tmp00);
2484   DAInt neighIInit00(tmp11);
2485   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2486   DataArrayInt *idsTmp=0;
2487   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2488   DAInt ids(idsTmp);
2489   if(!b)
2490     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2491   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2492   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2493   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2494   DataArrayInt *tmp0=0,*tmp1=0;
2495   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2496   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2497   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2498   DAInt neigh00(tmp0);
2499   DAInt neighI00(tmp1);
2500
2501   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2502   int seed = 0, nIter = 0;
2503   int nIterMax = nCells2+1; // Safety net for the loop
2504   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2505   hitCells->fillWithValue(-1);
2506   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2507   cellsToModifyConn0_torenum->alloc(0,1);
2508   while (nIter < nIterMax)
2509     {
2510       DAInt t = hitCells->getIdsEqual(-1);
2511       if (!t->getNumberOfTuples())
2512         break;
2513       // Connex zone without the crack (to compute the next seed really)
2514       int dnu;
2515       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2516       int cnt = 0;
2517       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2518         hitCells->setIJ(*ptr,0,1);
2519       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2520       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2521       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2522       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2523       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2524       DAInt nonHitCells = hitCells->getIdsEqual(-1);
2525       DAInt intersec = nonHitCells->buildIntersection(comple);
2526       if (intersec->getNumberOfTuples())
2527         { seed = intersec->getIJ(0,0); }
2528       else
2529         { break; }
2530       nIter++;
2531     }
2532   if (nIter >= nIterMax)
2533     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2534
2535   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2536   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2537   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2538   //
2539   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2540   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2541   nodeIdsToDuplicate=s3.retn();
2542 }
2543
2544 /*!
2545  * This method operates a modification of the connectivity and coords in \b this.
2546  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2547  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2548  * 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
2549  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2550  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2551  * 
2552  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2553  * 
2554  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2555  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2556  */
2557 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2558 {
2559   int nbOfNodes=getNumberOfNodes();
2560   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2561   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2562 }
2563
2564 /*!
2565  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2566  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2567  *
2568  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2569  *
2570  * \sa renumberNodesInConn
2571  */
2572 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2573 {
2574   checkConnectivityFullyDefined();
2575   int *conn(getNodalConnectivity()->getPointer());
2576   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2577   int nbOfCells(getNumberOfCells());
2578   for(int i=0;i<nbOfCells;i++)
2579     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2580       {
2581         int& node=conn[iconn];
2582         if(node>=0)//avoid polyhedron separator
2583           {
2584             node+=offset;
2585           }
2586       }
2587   _nodal_connec->declareAsNew();
2588   updateTime();
2589 }
2590
2591 /*!
2592  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2593  *  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
2594  *  of a big mesh.
2595  */
2596 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2597 {
2598   checkConnectivityFullyDefined();
2599   int *conn(getNodalConnectivity()->getPointer());
2600   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2601   int nbOfCells(getNumberOfCells());
2602   for(int i=0;i<nbOfCells;i++)
2603     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2604       {
2605         int& node=conn[iconn];
2606         if(node>=0)//avoid polyhedron separator
2607           {
2608             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2609             if(it!=newNodeNumbersO2N.end())
2610               {
2611                 node=(*it).second;
2612               }
2613             else
2614               {
2615                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2616                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2617               }
2618           }
2619       }
2620   _nodal_connec->declareAsNew();
2621   updateTime();
2622 }
2623
2624 /*!
2625  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2626  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2627  * This method is a generalization of shiftNodeNumbersInConn().
2628  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2629  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2630  *         this->getNumberOfNodes(), in "Old to New" mode. 
2631  *         See \ref numbering for more info on renumbering modes.
2632  *  \throw If the nodal connectivity of cells is not defined.
2633  *
2634  *  \if ENABLE_EXAMPLES
2635  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2636  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2637  *  \endif
2638  */
2639 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2640 {
2641   checkConnectivityFullyDefined();
2642   int *conn=getNodalConnectivity()->getPointer();
2643   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2644   int nbOfCells(getNumberOfCells());
2645   for(int i=0;i<nbOfCells;i++)
2646     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2647       {
2648         int& node=conn[iconn];
2649         if(node>=0)//avoid polyhedron separator
2650           {
2651             node=newNodeNumbersO2N[node];
2652           }
2653       }
2654   _nodal_connec->declareAsNew();
2655   updateTime();
2656 }
2657
2658 /*!
2659  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2660  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2661  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2662  * 
2663  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2664  */
2665 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2666 {
2667   checkConnectivityFullyDefined();
2668   int *conn=getNodalConnectivity()->getPointer();
2669   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2670   int nbOfCells=getNumberOfCells();
2671   for(int i=0;i<nbOfCells;i++)
2672     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2673       {
2674         int& node=conn[iconn];
2675         if(node>=0)//avoid polyhedron separator
2676           {
2677             node+=delta;
2678           }
2679       }
2680   _nodal_connec->declareAsNew();
2681   updateTime();
2682 }
2683
2684 /*!
2685  * This method operates a modification of the connectivity in \b this.
2686  * 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.
2687  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2688  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2689  * 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
2690  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2691  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2692  * 
2693  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2694  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2695  * 
2696  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2697  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2698  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2699  */
2700 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2701 {
2702   checkConnectivityFullyDefined();
2703   std::map<int,int> m;
2704   int val=offset;
2705   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2706     m[*work]=val;
2707   int *conn=getNodalConnectivity()->getPointer();
2708   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2709   int nbOfCells=getNumberOfCells();
2710   for(int i=0;i<nbOfCells;i++)
2711     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2712       {
2713         int& node=conn[iconn];
2714         if(node>=0)//avoid polyhedron separator
2715           {
2716             std::map<int,int>::iterator it=m.find(node);
2717             if(it!=m.end())
2718               node=(*it).second;
2719           }
2720       }
2721   updateTime();
2722 }
2723
2724 /*!
2725  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2726  *
2727  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2728  * After the call of this method the number of cells remains the same as before.
2729  *
2730  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2731  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2732  * be strictly in [0;this->getNumberOfCells()).
2733  *
2734  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2735  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2736  * should be contained in[0;this->getNumberOfCells()).
2737  * 
2738  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2739  * \param check
2740  */
2741 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2742 {
2743   checkConnectivityFullyDefined();
2744   int nbCells=getNumberOfCells();
2745   const int *array=old2NewBg;
2746   if(check)
2747     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2748   //
2749   const int *conn=_nodal_connec->getConstPointer();
2750   const int *connI=_nodal_connec_index->getConstPointer();
2751   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2752   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2753   const int *n2oPtr=n2o->begin();
2754   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2755   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2756   newConn->copyStringInfoFrom(*_nodal_connec);
2757   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2758   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2759   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2760   //
2761   int *newC=newConn->getPointer();
2762   int *newCI=newConnI->getPointer();
2763   int loc=0;
2764   newCI[0]=loc;
2765   for(int i=0;i<nbCells;i++)
2766     {
2767       int pos=n2oPtr[i];
2768       int nbOfElts=connI[pos+1]-connI[pos];
2769       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2770       loc+=nbOfElts;
2771       newCI[i+1]=loc;
2772     }
2773   //
2774   setConnectivity(newConn,newConnI);
2775   if(check)
2776     free(const_cast<int *>(array));
2777 }
2778
2779 /*!
2780  * Finds cells whose bounding boxes intersect a given bounding box.
2781  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2782  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2783  *         zMax (if in 3D). 
2784  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2785  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2786  *         extent of the bounding box of cell to produce an addition to this bounding box.
2787  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2788  *         cells. The caller is to delete this array using decrRef() as it is no more
2789  *         needed. 
2790  *  \throw If the coordinates array is not set.
2791  *  \throw If the nodal connectivity of cells is not defined.
2792  *
2793  *  \if ENABLE_EXAMPLES
2794  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2795  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2796  *  \endif
2797  */
2798 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2799 {
2800   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2801   if(getMeshDimension()==-1)
2802     {
2803       elems->pushBackSilent(0);
2804       return elems.retn();
2805     }
2806   int dim=getSpaceDimension();
2807   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2808   const int* conn      = getNodalConnectivity()->getConstPointer();
2809   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2810   const double* coords = getCoords()->getConstPointer();
2811   int nbOfCells=getNumberOfCells();
2812   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2813     {
2814       for (int i=0; i<dim; i++)
2815         {
2816           elem_bb[i*2]=std::numeric_limits<double>::max();
2817           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2818         }
2819
2820       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2821         {
2822           int node= conn[inode];
2823           if(node>=0)//avoid polyhedron separator
2824             {
2825               for (int idim=0; idim<dim; idim++)
2826                 {
2827                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2828                     {
2829                       elem_bb[idim*2] = coords[node*dim+idim] ;
2830                     }
2831                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2832                     {
2833                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2834                     }
2835                 }
2836             }
2837         }
2838       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2839         elems->pushBackSilent(ielem);
2840     }
2841   return elems.retn();
2842 }
2843
2844 /*!
2845  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2846  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2847  * added in 'elems' parameter.
2848  */
2849 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2850 {
2851   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2852   if(getMeshDimension()==-1)
2853     {
2854       elems->pushBackSilent(0);
2855       return elems.retn();
2856     }
2857   int dim=getSpaceDimension();
2858   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2859   const int* conn      = getNodalConnectivity()->getConstPointer();
2860   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2861   const double* coords = getCoords()->getConstPointer();
2862   int nbOfCells=getNumberOfCells();
2863   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2864     {
2865       for (int i=0; i<dim; i++)
2866         {
2867           elem_bb[i*2]=std::numeric_limits<double>::max();
2868           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2869         }
2870
2871       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2872         {
2873           int node= conn[inode];
2874           if(node>=0)//avoid polyhedron separator
2875             {
2876               for (int idim=0; idim<dim; idim++)
2877                 {
2878                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2879                     {
2880                       elem_bb[idim*2] = coords[node*dim+idim] ;
2881                     }
2882                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2883                     {
2884                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2885                     }
2886                 }
2887             }
2888         }
2889       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2890         elems->pushBackSilent(ielem);
2891     }
2892   return elems.retn();
2893 }
2894
2895 /*!
2896  * Returns a type of a cell by its id.
2897  *  \param [in] cellId - the id of the cell of interest.
2898  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2899  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2900  */
2901 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2902 {
2903   const int *ptI=_nodal_connec_index->getConstPointer();
2904   const int *pt=_nodal_connec->getConstPointer();
2905   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2906     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2907   else
2908     {
2909       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2910       throw INTERP_KERNEL::Exception(oss.str().c_str());
2911     }
2912 }
2913
2914 /*!
2915  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2916  * This method does not throw exception if geometric type \a type is not in \a this.
2917  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2918  * The coordinates array is not considered here.
2919  *
2920  * \param [in] type the geometric type
2921  * \return cell ids in this having geometric type \a type.
2922  */
2923 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2924 {
2925
2926   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2927   ret->alloc(0,1);
2928   checkConnectivityFullyDefined();
2929   int nbCells=getNumberOfCells();
2930   int mdim=getMeshDimension();
2931   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2932   if(mdim!=(int)cm.getDimension())
2933     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2934   const int *ptI=_nodal_connec_index->getConstPointer();
2935   const int *pt=_nodal_connec->getConstPointer();
2936   for(int i=0;i<nbCells;i++)
2937     {
2938       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2939         ret->pushBackSilent(i);
2940     }
2941   return ret.retn();
2942 }
2943
2944 /*!
2945  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2946  */
2947 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2948 {
2949   const int *ptI=_nodal_connec_index->getConstPointer();
2950   const int *pt=_nodal_connec->getConstPointer();
2951   int nbOfCells=getNumberOfCells();
2952   int ret=0;
2953   for(int i=0;i<nbOfCells;i++)
2954     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2955       ret++;
2956   return ret;
2957 }
2958
2959 /*!
2960  * Returns the nodal connectivity of a given cell.
2961  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2962  * all returned node ids can be used in getCoordinatesOfNode().
2963  *  \param [in] cellId - an id of the cell of interest.
2964  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2965  *         cleared before the appending.
2966  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2967  */
2968 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2969 {
2970   const int *ptI=_nodal_connec_index->getConstPointer();
2971   const int *pt=_nodal_connec->getConstPointer();
2972   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2973     if(*w>=0)
2974       conn.push_back(*w);
2975 }
2976
2977 std::string MEDCouplingUMesh::simpleRepr() const
2978 {
2979   static const char msg0[]="No coordinates specified !";
2980   std::ostringstream ret;
2981   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2982   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2983   int tmpp1,tmpp2;
2984   double tt=getTime(tmpp1,tmpp2);
2985   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2986   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2987   if(_mesh_dim>=-1)
2988     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2989   else
2990     { ret << " Mesh dimension has not been set or is invalid !"; }
2991   if(_coords!=0)
2992     {
2993       const int spaceDim=getSpaceDimension();
2994       ret << spaceDim << "\nInfo attached on space dimension : ";
2995       for(int i=0;i<spaceDim;i++)
2996         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2997       ret << "\n";
2998     }
2999   else
3000     ret << msg0 << "\n";
3001   ret << "Number of nodes : ";
3002   if(_coords!=0)
3003     ret << getNumberOfNodes() << "\n";
3004   else
3005     ret << msg0 << "\n";
3006   ret << "Number of cells : ";
3007   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3008     ret << getNumberOfCells() << "\n";
3009   else
3010     ret << "No connectivity specified !" << "\n";
3011   ret << "Cell types present : ";
3012   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3013     {
3014       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3015       ret << cm.getRepr() << " ";
3016     }
3017   ret << "\n";
3018   return ret.str();
3019 }
3020
3021 std::string MEDCouplingUMesh::advancedRepr() const
3022 {
3023   std::ostringstream ret;
3024   ret << simpleRepr();
3025   ret << "\nCoordinates array : \n___________________\n\n";
3026   if(_coords)
3027     _coords->reprWithoutNameStream(ret);
3028   else
3029     ret << "No array set !\n";
3030   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3031   reprConnectivityOfThisLL(ret);
3032   return ret.str();
3033 }
3034
3035 /*!
3036  * This method returns a C++ code that is a dump of \a this.
3037  * This method will throw if this is not fully defined.
3038  */
3039 std::string MEDCouplingUMesh::cppRepr() const
3040 {
3041   static const char coordsName[]="coords";
3042   static const char connName[]="conn";
3043   static const char connIName[]="connI";
3044   checkFullyDefined();
3045   std::ostringstream ret; ret << "// coordinates" << std::endl;
3046   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3047   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3048   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3049   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3050   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3051   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3052   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3053   return ret.str();
3054 }
3055
3056 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3057 {
3058   std::ostringstream ret;
3059   reprConnectivityOfThisLL(ret);
3060   return ret.str();
3061 }
3062
3063 /*!
3064  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3065  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3066  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3067  * some algos).
3068  * 
3069  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3070  * 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
3071  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3072  */
3073 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3074 {
3075   int mdim=getMeshDimension();
3076   if(mdim<0)
3077     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3078   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3079   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3080   bool needToCpyCT=true;
3081   if(!_nodal_connec)
3082     {
3083       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3084       needToCpyCT=false;
3085     }
3086   else
3087     {
3088       tmp1=_nodal_connec;
3089       tmp1->incrRef();
3090     }
3091   if(!_nodal_connec_index)
3092     {
3093       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3094       needToCpyCT=false;
3095     }
3096   else
3097     {
3098       tmp2=_nodal_connec_index;
3099       tmp2->incrRef();
3100     }
3101   ret->setConnectivity(tmp1,tmp2,false);
3102   if(needToCpyCT)
3103     ret->_types=_types;
3104   if(!_coords)
3105     {
3106       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3107       ret->setCoords(coords);
3108     }
3109   else
3110     ret->setCoords(_coords);
3111   return ret.retn();
3112 }
3113
3114 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3115 {
3116   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3117     {
3118       int nbOfCells=getNumberOfCells();
3119       const int *c=_nodal_connec->getConstPointer();
3120       const int *ci=_nodal_connec_index->getConstPointer();
3121       for(int i=0;i<nbOfCells;i++)
3122         {
3123           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3124           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3125           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3126           stream << "\n";
3127         }
3128     }
3129   else
3130     stream << "Connectivity not defined !\n";
3131 }
3132
3133 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3134 {
3135   const int *ptI=_nodal_connec_index->getConstPointer();
3136   const int *pt=_nodal_connec->getConstPointer();
3137   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3138     return ptI[cellId+1]-ptI[cellId]-1;
3139   else
3140     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3141 }
3142
3143 /*!
3144  * Returns types of cells of the specified part of \a this mesh.
3145  * This method avoids computing sub-mesh explicitely to get its types.
3146  *  \param [in] begin - an array of cell ids of interest.
3147  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3148  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3149  *         describing the cell types. 
3150  *  \throw If the coordinates array is not set.
3151  *  \throw If the nodal connectivity of cells is not defined.
3152  *  \sa getAllGeoTypes()
3153  */
3154 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3155 {
3156   checkFullyDefined();
3157   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3158   const int *conn=_nodal_connec->getConstPointer();
3159   const int *connIndex=_nodal_connec_index->getConstPointer();
3160   for(const int *w=begin;w!=end;w++)
3161     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3162   return ret;
3163 }
3164
3165 /*!
3166  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3167  * Optionally updates
3168  * a set of types of cells constituting \a this mesh. 
3169  * This method is for advanced users having prepared their connectivity before. For
3170  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3171  *  \param [in] conn - the nodal connectivity array. 
3172  *  \param [in] connIndex - the nodal connectivity index array.
3173  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3174  *         mesh is updated.
3175  */
3176 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3177 {
3178   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3179   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3180   if(isComputingTypes)
3181     computeTypes();
3182   declareAsNew();
3183 }
3184
3185 /*!
3186  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3187  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3188  */
3189 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3190     _nodal_connec(0),_nodal_connec_index(0),
3191     _types(other._types)
3192 {
3193   if(other._nodal_connec)
3194     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3195   if(other._nodal_connec_index)
3196     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3197 }
3198
3199 MEDCouplingUMesh::~MEDCouplingUMesh()
3200 {
3201   if(_nodal_connec)
3202     _nodal_connec->decrRef();
3203   if(_nodal_connec_index)
3204     _nodal_connec_index->decrRef();
3205 }
3206
3207 /*!
3208  * Recomputes a set of cell types of \a this mesh. For more info see
3209  * \ref MEDCouplingUMeshNodalConnectivity.
3210  */
3211 void MEDCouplingUMesh::computeTypes()
3212 {
3213   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3214 }
3215
3216 /*!
3217  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3218  */
3219 void MEDCouplingUMesh::checkFullyDefined() const
3220 {
3221   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3222     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3223 }
3224
3225 /*!
3226  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3227  */
3228 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3229 {
3230   if(!_nodal_connec_index || !_nodal_connec)
3231     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3232 }
3233
3234 /*!
3235  * Returns a number of cells constituting \a this mesh. 
3236  *  \return int - the number of cells in \a this mesh.
3237  *  \throw If the nodal connectivity of cells is not defined.
3238  */
3239 int MEDCouplingUMesh::getNumberOfCells() const
3240
3241   if(_nodal_connec_index)
3242     return _nodal_connec_index->getNumberOfTuples()-1;
3243   else
3244     if(_mesh_dim==-1)
3245       return 1;
3246     else
3247       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3248 }
3249
3250 /*!
3251  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3252  * mesh. For more info see \ref meshes.
3253  *  \return int - the dimension of \a this mesh.
3254  *  \throw If the mesh dimension is not defined using setMeshDimension().
3255  */
3256 int MEDCouplingUMesh::getMeshDimension() const
3257 {
3258   if(_mesh_dim<-1)
3259     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3260   return _mesh_dim;
3261 }
3262
3263 /*!
3264  * Returns a length of the nodal connectivity array.
3265  * This method is for test reason. Normally the integer returned is not useable by
3266  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3267  *  \return int - the length of the nodal connectivity array.
3268  */
3269 int MEDCouplingUMesh::getMeshLength() const
3270 {
3271   return _nodal_connec->getNbOfElems();
3272 }
3273
3274 /*!
3275  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3276  */
3277 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3278 {
3279   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3280   tinyInfo.push_back(getMeshDimension());
3281   tinyInfo.push_back(getNumberOfCells());
3282   if(_nodal_connec)
3283     tinyInfo.push_back(getMeshLength());
3284   else
3285     tinyInfo.push_back(-1);
3286 }
3287
3288 /*!
3289  * First step of unserialization process.
3290  */
3291 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3292 {
3293   return tinyInfo[6]<=0;
3294 }
3295
3296 /*!
3297  * Second step of serialization process.
3298  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3299  * \param a1
3300  * \param a2
3301  * \param littleStrings
3302  */
3303 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3304 {
3305   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3306   if(tinyInfo[5]!=-1)
3307     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3308 }
3309
3310 /*!
3311  * Third and final step of serialization process.
3312  */
3313 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3314 {
3315   MEDCouplingPointSet::serialize(a1,a2);
3316   if(getMeshDimension()>-1)
3317     {
3318       a1=DataArrayInt::New();
3319       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3320       int *ptA1=a1->getPointer();
3321       const int *conn=getNodalConnectivity()->getConstPointer();
3322       const int *index=getNodalConnectivityIndex()->getConstPointer();
3323       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3324       std::copy(conn,conn+getMeshLength(),ptA1);
3325     }
3326   else
3327     a1=0;
3328 }
3329
3330 /*!
3331  * Second and final unserialization process.
3332  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3333  */
3334 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3335 {
3336   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3337   setMeshDimension(tinyInfo[5]);
3338   if(tinyInfo[7]!=-1)
3339     {
3340       // Connectivity
3341       const int *recvBuffer=a1->getConstPointer();
3342       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3343       myConnecIndex->alloc(tinyInfo[6]+1,1);
3344       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3345       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3346       myConnec->alloc(tinyInfo[7],1);
3347       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3348       setConnectivity(myConnec, myConnecIndex);
3349     }
3350 }
3351
3352 /*!
3353  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3354  * CellIds are given using range specified by a start an end and step.
3355  */
3356 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3357 {
3358   checkFullyDefined();
3359   int ncell=getNumberOfCells();
3360   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3361   ret->_mesh_dim=_mesh_dim;
3362   ret->setCoords(_coords);
3363   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3364   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3365   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3366   int work=start;
3367   const int *conn=_nodal_connec->getConstPointer();
3368   const int *connIndex=_nodal_connec_index->getConstPointer();
3369   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3370     {
3371       if(work>=0 && work<ncell)
3372         {
3373           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3374         }
3375       else
3376         {
3377           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3378           throw INTERP_KERNEL::Exception(oss.str().c_str());
3379         }
3380     }
3381   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3382   int *newConnPtr=newConn->getPointer();
3383   std::set<INTERP_KERNEL::NormalizedCellType> types;
3384   work=start;
3385   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3386     {
3387       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3388       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3389     }
3390   ret->setConnectivity(newConn,newConnI,false);
3391   ret->_types=types;
3392   ret->copyTinyInfoFrom(this);
3393   return ret.retn();
3394 }
3395
3396 /*!
3397  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3398  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3399  * The return newly allocated mesh will share the same coordinates as \a this.
3400  */
3401 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3402 {
3403   checkConnectivityFullyDefined();
3404   int ncell=getNumberOfCells();
3405   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3406   ret->_mesh_dim=_mesh_dim;
3407   ret->setCoords(_coords);
3408   std::size_t nbOfElemsRet=std::distance(begin,end);
3409   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3410   connIndexRet[0]=0;
3411   const int *conn=_nodal_connec->getConstPointer();
3412   const int *connIndex=_nodal_connec_index->getConstPointer();
3413   int newNbring=0;
3414   for(const int *work=begin;work!=end;work++,newNbring++)
3415     {
3416       if(*work>=0 && *work<ncell)
3417         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3418       else
3419         {
3420           free(connIndexRet);
3421           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3422           throw INTERP_KERNEL::Exception(oss.str().c_str());
3423         }
3424     }
3425   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3426   int *connRetWork=connRet;
3427   std::set<INTERP_KERNEL::NormalizedCellType> types;
3428   for(const int *work=begin;work!=end;work++)
3429     {
3430       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3431       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3432     }
3433   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3434   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3435   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3436   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3437   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3438   ret->_types=types;
3439   ret->copyTinyInfoFrom(this);
3440   return ret.retn();
3441 }
3442
3443 /*!
3444  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3445  * mesh.<br>
3446  * For 1D cells, the returned field contains lengths.<br>
3447  * For 2D cells, the returned field contains areas.<br>
3448  * For 3D cells, the returned field contains volumes.
3449  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3450  *         orientation, i.e. the volume is always positive.
3451  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3452  *         and one time . The caller is to delete this field using decrRef() as it is no
3453  *         more needed.
3454  */
3455 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3456 {
3457   std::string name="MeasureOfMesh_";
3458   name+=getName();
3459   int nbelem=getNumberOfCells();
3460   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3461   field->setName(name);
3462   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3463   array->alloc(nbelem,1);
3464   double *area_vol=array->getPointer();
3465   field->setArray(array) ; array=0;
3466   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3467   field->synchronizeTimeWithMesh();
3468   if(getMeshDimension()!=-1)
3469     {
3470       int ipt;
3471       INTERP_KERNEL::NormalizedCellType type;
3472       int dim_space=getSpaceDimension();
3473       const double *coords=getCoords()->getConstPointer();
3474       const int *connec=getNodalConnectivity()->getConstPointer();
3475       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3476       for(int iel=0;iel<nbelem;iel++)
3477         {
3478           ipt=connec_index[iel];
3479           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3480           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);
3481         }
3482       if(isAbs)
3483         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3484     }
3485   else
3486     {
3487       area_vol[0]=std::numeric_limits<double>::max();
3488     }
3489   return field.retn();
3490 }
3491
3492 /*!
3493  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3494  * mesh.<br>
3495  * For 1D cells, the returned array contains lengths.<br>
3496  * For 2D cells, the returned array contains areas.<br>
3497  * For 3D cells, the returned array contains volumes.
3498  * This method avoids building explicitly a part of \a this mesh to perform the work.
3499  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3500  *         orientation, i.e. the volume is always positive.
3501  *  \param [in] begin - an array of cell ids of interest.
3502  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3503  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3504  *          delete this array using decrRef() as it is no more needed.
3505  * 
3506  *  \if ENABLE_EXAMPLES
3507  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3508  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3509  *  \endif
3510  *  \sa getMeasureField()
3511  */
3512 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3513 {
3514   std::string name="PartMeasureOfMesh_";
3515   name+=getName();
3516   int nbelem=(int)std::distance(begin,end);
3517   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3518   array->setName(name);
3519   array->alloc(nbelem,1);
3520   double *area_vol=array->getPointer();
3521   if(getMeshDimension()!=-1)
3522     {
3523       int ipt;
3524       INTERP_KERNEL::NormalizedCellType type;
3525       int dim_space=getSpaceDimension();
3526       const double *coords=getCoords()->getConstPointer();
3527       const int *connec=getNodalConnectivity()->getConstPointer();
3528       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3529       for(const int *iel=begin;iel!=end;iel++)
3530         {
3531           ipt=connec_index[*iel];
3532           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3533           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3534         }
3535       if(isAbs)
3536         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3537     }
3538   else
3539     {
3540       area_vol[0]=std::numeric_limits<double>::max();
3541     }
3542   return array.retn();
3543 }
3544
3545 /*!
3546  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3547  * \a this one. The returned field contains the dual cell volume for each corresponding
3548  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3549  *  the dual mesh in P1 sens of \a this.<br>
3550  * For 1D cells, the returned field contains lengths.<br>
3551  * For 2D cells, the returned field contains areas.<br>
3552  * For 3D cells, the returned field contains volumes.
3553  * This method is useful to check "P1*" conservative interpolators.
3554  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3555  *         orientation, i.e. the volume is always positive.
3556  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3557  *          nodes and one time. The caller is to delete this array using decrRef() as
3558  *          it is no more needed.
3559  */
3560 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3561 {
3562   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3563   std::string name="MeasureOnNodeOfMesh_";
3564   name+=getName();
3565   int nbNodes=getNumberOfNodes();
3566   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3567   double cst=1./((double)getMeshDimension()+1.);
3568   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3569   array->alloc(nbNodes,1);
3570   double *valsToFill=array->getPointer();
3571   std::fill(valsToFill,valsToFill+nbNodes,0.);
3572   const double *values=tmp->getArray()->getConstPointer();
3573   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3574   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3575   getReverseNodalConnectivity(da,daInd);
3576   const int *daPtr=da->getConstPointer();
3577   const int *daIPtr=daInd->getConstPointer();
3578   for(int i=0;i<nbNodes;i++)
3579     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3580       valsToFill[i]+=cst*values[*cell];
3581   ret->setMesh(this);
3582   ret->setArray(array);
3583   return ret.retn();
3584 }
3585
3586 /*!
3587  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3588  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3589  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3590  * and are normalized.
3591  * <br> \a this can be either 
3592  * - a  2D mesh in 2D or 3D space or 
3593  * - an 1D mesh in 2D space.
3594  * 
3595  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3596  *          cells and one time. The caller is to delete this field using decrRef() as
3597  *          it is no more needed.
3598  *  \throw If the nodal connectivity of cells is not defined.
3599  *  \throw If the coordinates array is not set.
3600  *  \throw If the mesh dimension is not set.
3601  *  \throw If the mesh and space dimension is not as specified above.
3602  */
3603 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3604 {
3605   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3606     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3607   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3608   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3609   int nbOfCells=getNumberOfCells();
3610   int nbComp=getMeshDimension()+1;
3611   array->alloc(nbOfCells,nbComp);
3612   double *vals=array->getPointer();
3613   const int *connI=_nodal_connec_index->getConstPointer();
3614   const int *conn=_nodal_connec->getConstPointer();
3615   const double *coords=_coords->getConstPointer();
3616   if(getMeshDimension()==2)
3617     {
3618       if(getSpaceDimension()==3)
3619         {
3620           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3621           const double *locPtr=loc->getConstPointer();
3622           for(int i=0;i<nbOfCells;i++,vals+=3)
3623             {
3624               int offset=connI[i];
3625               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3626               double n=INTERP_KERNEL::norm<3>(vals);
3627               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3628             }
3629         }
3630       else
3631         {
3632           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3633           const double *isAbsPtr=isAbs->getArray()->begin();
3634           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3635             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3636         }
3637     }
3638   else//meshdimension==1
3639     {
3640       double tmp[2];
3641       for(int i=0;i<nbOfCells;i++)
3642         {
3643           int offset=connI[i];
3644           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3645           double n=INTERP_KERNEL::norm<2>(tmp);
3646           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3647           *vals++=-tmp[1];
3648           *vals++=tmp[0];
3649         }
3650     }
3651   ret->setArray(array);
3652   ret->setMesh(this);
3653   ret->synchronizeTimeWithSupport();
3654   return ret.retn();
3655 }
3656
3657 /*!
3658  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3659  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3660  * and are normalized.
3661  * <br> \a this can be either 
3662  * - a  2D mesh in 2D or 3D space or 
3663  * - an 1D mesh in 2D space.
3664  * 
3665  * This method avoids building explicitly a part of \a this mesh to perform the work.
3666  *  \param [in] begin - an array of cell ids of interest.
3667  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3668  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3669  *          cells and one time. The caller is to delete this field using decrRef() as
3670  *          it is no more needed.
3671  *  \throw If the nodal connectivity of cells is not defined.
3672  *  \throw If the coordinates array is not set.
3673  *  \throw If the mesh dimension is not set.
3674  *  \throw If the mesh and space dimension is not as specified above.
3675  *  \sa buildOrthogonalField()
3676  *
3677  *  \if ENABLE_EXAMPLES
3678  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3679  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3680  *  \endif
3681  */
3682 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3683 {
3684   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3685     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3686   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3687   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3688   std::size_t nbelems=std::distance(begin,end);
3689   int nbComp=getMeshDimension()+1;
3690   array->alloc((int)nbelems,nbComp);
3691   double *vals=array->getPointer();
3692   const int *connI=_nodal_connec_index->getConstPointer();
3693   const int *conn=_nodal_connec->getConstPointer();
3694   const double *coords=_coords->getConstPointer();
3695   if(getMeshDimension()==2)
3696     {
3697       if(getSpaceDimension()==3)
3698         {
3699           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3700           const double *locPtr=loc->getConstPointer();
3701           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3702             {
3703               int offset=connI[*i];
3704               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3705               double n=INTERP_KERNEL::norm<3>(vals);
3706               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3707             }
3708         }
3709       else
3710         {
3711           for(std::size_t i=0;i<nbelems;i++)
3712             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3713         }
3714     }
3715   else//meshdimension==1
3716     {
3717       double tmp[2];
3718       for(const int *i=begin;i!=end;i++)
3719         {
3720           int offset=connI[*i];
3721           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3722           double n=INTERP_KERNEL::norm<2>(tmp);
3723           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3724           *vals++=-tmp[1];
3725           *vals++=tmp[0];
3726         }
3727     }
3728   ret->setArray(array);
3729   ret->setMesh(this);
3730   ret->synchronizeTimeWithSupport();
3731   return ret.retn();
3732 }
3733
3734 /*!
3735  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3736  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3737  * and are \b not normalized.
3738  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3739  *          cells and one time. The caller is to delete this field using decrRef() as
3740  *          it is no more needed.
3741  *  \throw If the nodal connectivity of cells is not defined.
3742  *  \throw If the coordinates array is not set.
3743  *  \throw If \a this->getMeshDimension() != 1.
3744  *  \throw If \a this mesh includes cells of type other than SEG2.
3745  */
3746 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3747 {
3748   if(getMeshDimension()!=1)
3749     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3750   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3751     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3752   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3753   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3754   int nbOfCells=getNumberOfCells();
3755   int spaceDim=getSpaceDimension();
3756   array->alloc(nbOfCells,spaceDim);
3757   double *pt=array->getPointer();
3758   const double *coo=getCoords()->getConstPointer();
3759   std::vector<int> conn;
3760   conn.reserve(2);
3761   for(int i=0;i<nbOfCells;i++)
3762     {
3763       conn.resize(0);
3764       getNodeIdsOfCell(i,conn);
3765       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3766     }
3767   ret->setArray(array);
3768   ret->setMesh(this);
3769   ret->synchronizeTimeWithSupport();
3770   return ret.retn();
3771 }
3772
3773 /*!
3774  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3775  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3776  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3777  * from. If a result face is shared by two 3D cells, then the face in included twice in
3778  * the result mesh.
3779  *  \param [in] origin - 3 components of a point defining location of the plane.
3780  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3781  *         must be greater than 1e-6.
3782  *  \param [in] eps - half-thickness of the plane.
3783  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3784  *         producing correspondent 2D cells. The caller is to delete this array
3785  *         using decrRef() as it is no more needed.
3786  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3787  *         not share the node coordinates array with \a this mesh. The caller is to
3788  *         delete this mesh using decrRef() as it is no more needed.  
3789  *  \throw If the coordinates array is not set.
3790  *  \throw If the nodal connectivity of cells is not defined.
3791  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3792  *  \throw If magnitude of \a vec is less than 1e-6.
3793  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3794  *  \throw If \a this includes quadratic cells.
3795  */
3796 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3797 {
3798   checkFullyDefined();
3799   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3800     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3801   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3802   if(candidates->empty())
3803     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3804   std::vector<int> nodes;
3805   DataArrayInt *cellIds1D=0;
3806   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3807   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3808   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3809   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3810   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3811   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3812   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3813   revDesc2=0; revDescIndx2=0;
3814   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3815   revDesc1=0; revDescIndx1=0;
3816   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3817   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3818   //
3819   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3820   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3821     cut3DCurve[*it]=-1;
3822   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3823   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3824   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3825                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3826                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3827   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3828   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3829   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3830   if(cellIds2->empty())
3831     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3832   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3833   ret->setCoords(mDesc1->getCoords());
3834   ret->setConnectivity(conn,connI,true);
3835   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3836   return ret.retn();
3837 }
3838
3839 /*!
3840  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3841 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
3842 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3843 the result mesh.
3844  *  \param [in] origin - 3 components of a point defining location of the plane.
3845  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3846  *         must be greater than 1e-6.
3847  *  \param [in] eps - half-thickness of the plane.
3848  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3849  *         producing correspondent segments. The caller is to delete this array
3850  *         using decrRef() as it is no more needed.
3851  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3852  *         mesh in 3D space. This mesh does not share the node coordinates array with
3853  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3854  *         no more needed. 
3855  *  \throw If the coordinates array is not set.
3856  *  \throw If the nodal connectivity of cells is not defined.
3857  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3858  *  \throw If magnitude of \a vec is less than 1e-6.
3859  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3860  *  \throw If \a this includes quadratic cells.
3861  */
3862 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3863 {
3864   checkFullyDefined();
3865   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3866     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3867   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3868   if(candidates->empty())
3869     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3870   std::vector<int> nodes;
3871   DataArrayInt *cellIds1D=0;
3872   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3873   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3874   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3875   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3876   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3878   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3879   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3881   //
3882   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3883   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3884     cut3DCurve[*it]=-1;
3885   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3886   int ncellsSub=subMesh->getNumberOfCells();
3887   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3888   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3889                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3890                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3891   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3892   conn->alloc(0,1);
3893   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3894   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3895   for(int i=0;i<ncellsSub;i++)
3896     {
3897       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3898         {
3899           if(cut3DSurf[i].first!=-2)
3900             {
3901               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3902               connI->pushBackSilent(conn->getNumberOfTuples());
3903               cellIds2->pushBackSilent(i);
3904             }
3905           else
3906             {
3907               int cellId3DSurf=cut3DSurf[i].second;
3908               int offset=nodalI[cellId3DSurf]+1;
3909               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3910               for(int j=0;j<nbOfEdges;j++)
3911                 {
3912                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3913                   connI->pushBackSilent(conn->getNumberOfTuples());
3914                   cellIds2->pushBackSilent(cellId3DSurf);
3915                 }
3916             }
3917         }
3918     }
3919   if(cellIds2->empty())
3920     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3921   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3922   ret->setCoords(mDesc1->getCoords());
3923   ret->setConnectivity(conn,connI,true);
3924   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3925   return ret.retn();
3926 }
3927
3928 /*!
3929  * Finds cells whose bounding boxes intersect a given plane.
3930  *  \param [in] origin - 3 components of a point defining location of the plane.
3931  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3932  *         must be greater than 1e-6.
3933  *  \param [in] eps - half-thickness of the plane.
3934  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3935  *         cells. The caller is to delete this array using decrRef() as it is no more
3936  *         needed.
3937  *  \throw If the coordinates array is not set.
3938  *  \throw If the nodal connectivity of cells is not defined.
3939  *  \throw If \a this->getSpaceDimension() != 3.
3940  *  \throw If magnitude of \a vec is less than 1e-6.
3941  *  \sa buildSlice3D()
3942  */
3943 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3944 {
3945   checkFullyDefined();
3946   if(getSpaceDimension()!=3)
3947     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3948   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3949   if(normm<1e-6)
3950     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3951   double vec2[3];
3952   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3953   double angle=acos(vec[2]/normm);
3954   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3955   double bbox[6];
3956   if(angle>eps)
3957     {
3958       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3959       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3960       if(normm2/normm>1e-6)
3961         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3962       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3963       mw->setCoords(coo);
3964       mw->getBoundingBox(bbox);
3965       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3966       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3967     }
3968   else
3969     {
3970       getBoundingBox(bbox);
3971       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3972       cellIds=getCellsInBoundingBox(bbox,eps);
3973     }
3974   return cellIds.retn();
3975 }
3976
3977 /*!
3978  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3979  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3980  * No consideration of coordinate is done by this method.
3981  * 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)
3982  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3983  */
3984 bool MEDCouplingUMesh::isContiguous1D() const
3985 {
3986   if(getMeshDimension()!=1)
3987     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3988   int nbCells=getNumberOfCells();
3989   if(nbCells<1)
3990     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3991   const int *connI=_nodal_connec_index->getConstPointer();
3992   const int *conn=_nodal_connec->getConstPointer();
3993   int ref=conn[connI[0]+2];
3994   for(int i=1;i<nbCells;i++)
3995     {
3996       if(conn[connI[i]+1]!=ref)
3997         return false;
3998       ref=conn[connI[i]+2];
3999     }
4000   return true;
4001 }
4002
4003 /*!
4004  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4005  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4006  * \param pt reference point of the line
4007  * \param v normalized director vector of the line
4008  * \param eps max precision before throwing an exception
4009  * \param res output of size this->getNumberOfCells
4010  */
4011 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4012 {
4013   if(getMeshDimension()!=1)
4014     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4015   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4016     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4017   if(getSpaceDimension()!=3)
4018     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4019   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4020   const double *fPtr=f->getArray()->getConstPointer();
4021   double tmp[3];
4022   for(int i=0;i<getNumberOfCells();i++)
4023     {
4024       const double *tmp1=fPtr+3*i;
4025       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4026       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4027       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4028       double n1=INTERP_KERNEL::norm<3>(tmp);
4029       n1/=INTERP_KERNEL::norm<3>(tmp1);
4030       if(n1>eps)
4031         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4032     }
4033   const double *coo=getCoords()->getConstPointer();
4034   for(int i=0;i<getNumberOfNodes();i++)
4035     {
4036       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4037       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4038       res[i]=std::accumulate(tmp,tmp+3,0.);
4039     }
4040 }
4041
4042 /*!
4043  * 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. 
4044  * \a this is expected to be a mesh so that its space dimension is equal to its
4045  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4046  * 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).
4047  *
4048  * 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
4049  * 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).
4050  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4051  *
4052  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4053  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4054  *
4055  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4056  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4057  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4058  * \return the positive value of the distance.
4059  * \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
4060  * dimension - 1.
4061  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4062  */
4063 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4064 {
4065   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4066   if(meshDim!=spaceDim-1)
4067     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4068   if(meshDim!=2 && meshDim!=1)
4069     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4070   checkFullyDefined();
4071   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4072     { 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()); }
4073   DataArrayInt *ret1=0;
4074   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4075   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4076   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4077   cellId=*ret1Safe->begin();
4078   return *ret0->begin();
4079 }
4080
4081 /*!
4082  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4083  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4084  * 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
4085  * 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).
4086  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4087  * 
4088  * \a this is expected to be a mesh so that its space dimension is equal to its
4089  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4090  * 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).
4091  *
4092  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4093  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4094  *
4095  * \param [in] pts the list of points in which each tuple represents a point
4096  * \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.
4097  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4098  * \throw if number of components of \a pts is not equal to the space dimension.
4099  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4100  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4101  */
4102 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4103 {
4104   if(!pts)
4105     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4106   pts->checkAllocated();
4107   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4108   if(meshDim!=spaceDim-1)
4109     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4110   if(meshDim!=2 && meshDim!=1)
4111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4112   if(pts->getNumberOfComponents()!=spaceDim)
4113     {
4114       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4115       throw INTERP_KERNEL::Exception(oss.str().c_str());
4116     }
4117   checkFullyDefined();
4118   int nbCells=getNumberOfCells();
4119   if(nbCells==0)
4120     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4121   int nbOfPts=pts->getNumberOfTuples();
4122   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4123   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4124   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4125   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4126   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4127   const double *bbox(bboxArr->begin());
4128   switch(spaceDim)
4129   {
4130     case 3:
4131       {
4132         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4133         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4134           {
4135             double x=std::numeric_limits<double>::max();
4136             std::vector<int> elems;
4137             myTree.getMinDistanceOfMax(ptsPtr,x);
4138             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4139             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4140           }
4141         break;
4142       }
4143     case 2:
4144       {
4145         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4146         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4147           {
4148             double x=std::numeric_limits<double>::max();
4149             std::vector<int> elems;
4150             myTree.getMinDistanceOfMax(ptsPtr,x);
4151             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4152             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4153           }
4154         break;
4155       }
4156     default:
4157       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4158   }
4159   cellIds=ret1.retn();
4160   return ret0.retn();
4161 }
4162
4163 /*!
4164  * \param [in] pt the start pointer (included) of the coordinates of the point
4165  * \param [in] cellIdsBg the start pointer (included) of cellIds
4166  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4167  * \param [in] nc nodal connectivity
4168  * \param [in] ncI nodal connectivity index
4169  * \param [in,out] ret0 the min distance between \a this and the external input point
4170  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4171  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4172  */
4173 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)
4174 {
4175   cellId=-1;
4176   ret0=std::numeric_limits<double>::max();
4177   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4178     {
4179       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4180       {
4181         case INTERP_KERNEL::NORM_TRI3:
4182           {
4183             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4184             if(tmp<ret0)
4185               { ret0=tmp; cellId=*zeCell; }
4186             break;
4187           }
4188         case INTERP_KERNEL::NORM_QUAD4:
4189         case INTERP_KERNEL::NORM_POLYGON:
4190           {
4191             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4192             if(tmp<ret0)
4193               { ret0=tmp; cellId=*zeCell; }
4194             break;
4195           }
4196         default:
4197           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4198       }
4199     }
4200 }
4201
4202 /*!
4203  * \param [in] pt the start pointer (included) of the coordinates of the point
4204  * \param [in] cellIdsBg the start pointer (included) of cellIds
4205  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4206  * \param [in] nc nodal connectivity
4207  * \param [in] ncI nodal connectivity index
4208  * \param [in,out] ret0 the min distance between \a this and the external input point
4209  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4210  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4211  */
4212 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)
4213 {
4214   cellId=-1;
4215   ret0=std::numeric_limits<double>::max();
4216   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4217     {
4218       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4219       {
4220         case INTERP_KERNEL::NORM_SEG2:
4221           {
4222             std::size_t uselessEntry=0;
4223             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4224             tmp=sqrt(tmp);
4225             if(tmp<ret0)
4226               { ret0=tmp; cellId=*zeCell; }
4227             break;
4228           }
4229         default:
4230           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4231       }
4232     }
4233 }
4234
4235 /*!
4236  * Finds cells in contact with a ball (i.e. a point with precision). 
4237  * 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.
4238  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4239  *
4240  * \warning This method is suitable if the caller intends to evaluate only one
4241  *          point, for more points getCellsContainingPoints() is recommended as it is
4242  *          faster. 
4243  *  \param [in] pos - array of coordinates of the ball central point.
4244  *  \param [in] eps - ball radius.
4245  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4246  *         if there are no such cells.
4247  *  \throw If the coordinates array is not set.
4248  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4249  */
4250 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4251 {
4252   std::vector<int> elts;
4253   getCellsContainingPoint(pos,eps,elts);
4254   if(elts.empty())
4255     return -1;
4256   return elts.front();
4257 }
4258
4259 /*!
4260  * Finds cells in contact with a ball (i.e. a point with precision).
4261  * 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.
4262  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4263  * \warning This method is suitable if the caller intends to evaluate only one
4264  *          point, for more points getCellsContainingPoints() is recommended as it is
4265  *          faster. 
4266  *  \param [in] pos - array of coordinates of the ball central point.
4267  *  \param [in] eps - ball radius.
4268  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4269  *         before inserting ids.
4270  *  \throw If the coordinates array is not set.
4271  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4272  *
4273  *  \if ENABLE_EXAMPLES
4274  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4275  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4276  *  \endif
4277  */
4278 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4279 {
4280   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4281   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4282   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4283 }
4284
4285 /// @cond INTERNAL
4286
4287 namespace ParaMEDMEM
4288 {
4289   template<const int SPACEDIMM>
4290   class DummyClsMCUG
4291   {
4292   public:
4293     static const int MY_SPACEDIM=SPACEDIMM;
4294     static const int MY_MESHDIM=8;
4295     typedef int MyConnType;
4296     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4297     // begin
4298     // useless, but for windows compilation ...
4299     const double* getCoordinatesPtr() const { return 0; }
4300     const int* getConnectivityPtr() const { return 0; }
4301     const int* getConnectivityIndexPtr() const { return 0; }
4302     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4303     // end
4304   };
4305
4306   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4307   {
4308     INTERP_KERNEL::Edge *ret(0);
4309     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]));
4310     m[n0]=bg[0]; m[n1]=bg[1];
4311     switch(typ)
4312     {
4313       case INTERP_KERNEL::NORM_SEG2:
4314         {
4315           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4316           break;
4317         }
4318       case INTERP_KERNEL::NORM_SEG3:
4319         {
4320           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4321           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4322           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4323           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4324           bool colinearity(inters.areColinears());
4325           delete e1; delete e2;
4326           if(colinearity)
4327             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4328           else
4329             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4330           break;
4331         }
4332       default:
4333         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4334     }
4335     return ret;
4336   }
4337
4338   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4339   {
4340     INTERP_KERNEL::Edge *ret=0;
4341     switch(typ)
4342     {
4343       case INTERP_KERNEL::NORM_SEG2:
4344         {
4345           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4346           break;
4347         }
4348       case INTERP_KERNEL::NORM_SEG3:
4349         {
4350           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4351           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4352           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4353           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4354           bool colinearity=inters.areColinears();
4355           delete e1; delete e2;
4356           if(colinearity)
4357             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4358           else
4359             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4360           mapp2[bg[2]].second=false;
4361           break;
4362         }
4363       default:
4364         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4365     }
4366     return ret;
4367   }
4368
4369   /*!
4370    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4371    * the global mesh 'mDesc'.
4372    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4373    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4374    */
4375   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4376                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4377   {
4378     mapp.clear();
4379     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.
4380     const double *coo=mDesc->getCoords()->getConstPointer();
4381     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4382     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4383     std::set<int> s;
4384     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4385       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4386     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4387       {
4388         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4389         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4390       }
4391     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4392     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4393       {
4394         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4395         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4396       }
4397     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4398       {
4399         if((*it2).second.second)
4400           mapp[(*it2).second.first]=(*it2).first;
4401         ((*it2).second.first)->decrRef();
4402       }
4403     return ret;
4404   }
4405
4406   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4407   {
4408     if(nodeId>=offset2)
4409       {
4410         int locId=nodeId-offset2;
4411         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4412       }
4413     if(nodeId>=offset1)
4414       {
4415         int locId=nodeId-offset1;
4416         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4417       }
4418     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4419   }
4420
4421   /**
4422    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4423    */
4424   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4425                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4426                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4427   {
4428     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4429       {
4430         int eltId1=abs(*desc1)-1;
4431         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4432           {
4433             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4434             if(it==mappRev.end())
4435               {
4436                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4437                 mapp[node]=*it1;
4438                 mappRev[*it1]=node;
4439               }
4440           }
4441       }
4442   }
4443 }
4444
4445 /// @endcond
4446
4447 template<int SPACEDIM>
4448 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4449                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4450 {
4451   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4452   int *eltsIndexPtr(eltsIndex->getPointer());
4453   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4454   const double *bbox(bboxArr->begin());
4455   int nbOfCells=getNumberOfCells();
4456   const int *conn=_nodal_connec->getConstPointer();
4457   const int *connI=_nodal_connec_index->getConstPointer();
4458   double bb[2*SPACEDIM];
4459   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4460   for(int i=0;i<nbOfPoints;i++)
4461     {
4462       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4463       for(int j=0;j<SPACEDIM;j++)
4464         {
4465           bb[2*j]=pos[SPACEDIM*i+j];
4466           bb[2*j+1]=pos[SPACEDIM*i+j];
4467         }
4468       std::vector<int> candidates;
4469       myTree.getIntersectingElems(bb,candidates);
4470       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4471         {
4472           int sz(connI[(*iter)+1]-connI[*iter]-1);
4473           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4474           bool status(false);
4475           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4476             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4477           else
4478             {
4479               if(SPACEDIM!=2)
4480                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4481               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4482               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4483               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4484               INTERP_KERNEL::QuadraticPolygon *pol(0);
4485               for(int j=0;j<sz;j++)
4486                 {
4487                   int nodeId(conn[connI[*iter]+1+j]);
4488                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4489                 }
4490               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4491                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4492               else
4493                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4494               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4495               double a(0.),b(0.),c(0.);
4496               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4497               status=pol->isInOrOut2(n);
4498               delete pol; n->decrRef();
4499             }
4500           if(status)
4501             {
4502               eltsIndexPtr[i+1]++;
4503               elts->pushBackSilent(*iter);
4504             }
4505         }
4506     }
4507 }
4508 /*!
4509  * Finds cells in contact with several balls (i.e. points with precision).
4510  * This method is an extension of getCellContainingPoint() and
4511  * getCellsContainingPoint() for the case of multiple points.
4512  * 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.
4513  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4514  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4515  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4516  *         this->getSpaceDimension() * \a nbOfPoints 
4517  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4518  *  \param [in] eps - radius of balls (i.e. the precision).
4519  *  \param [out] elts - vector returning ids of found cells.
4520  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4521  *         dividing cell ids in \a elts into groups each referring to one
4522  *         point. Its every element (except the last one) is an index pointing to the
4523  *         first id of a group of cells. For example cells in contact with the *i*-th
4524  *         point are described by following range of indices:
4525  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4526  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4527  *         Number of cells in contact with the *i*-th point is
4528  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4529  *  \throw If the coordinates array is not set.
4530  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4531  *
4532  *  \if ENABLE_EXAMPLES
4533  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4534  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4535  *  \endif
4536  */
4537 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4538                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4539 {
4540   int spaceDim=getSpaceDimension();
4541   int mDim=getMeshDimension();
4542   if(spaceDim==3)
4543     {
4544       if(mDim==3)
4545         {
4546           const double *coords=_coords->getConstPointer();
4547           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4548         }
4549       /*else if(mDim==2)
4550         {
4551
4552         }*/
4553       else
4554         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4555     }
4556   else if(spaceDim==2)
4557     {
4558       if(mDim==2)
4559         {
4560           const double *coords=_coords->getConstPointer();
4561           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4562         }
4563       else
4564         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4565     }
4566   else if(spaceDim==1)
4567     {
4568       if(mDim==1)
4569         {
4570           const double *coords=_coords->getConstPointer();
4571           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4572         }
4573       else
4574         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4575     }
4576   else
4577     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4578 }
4579
4580 /*!
4581  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4582  * least two its edges intersect each other anywhere except their extremities. An
4583  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4584  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4585  *         cleared before filling in.
4586  *  \param [in] eps - precision.
4587  *  \throw If \a this->getMeshDimension() != 2.
4588  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4589  */
4590 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4591 {
4592   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4593   if(getMeshDimension()!=2)
4594     throw INTERP_KERNEL::Exception(msg);
4595   int spaceDim=getSpaceDimension();
4596   if(spaceDim!=2 && spaceDim!=3)
4597     throw INTERP_KERNEL::Exception(msg);
4598   const int *conn=_nodal_connec->getConstPointer();
4599   const int *connI=_nodal_connec_index->getConstPointer();
4600   int nbOfCells=getNumberOfCells();
4601   std::vector<double> cell2DinS2;
4602   for(int i=0;i<nbOfCells;i++)
4603     {
4604       int offset=connI[i];
4605       int nbOfNodesForCell=connI[i+1]-offset-1;
4606       if(nbOfNodesForCell<=3)
4607         continue;
4608       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4609       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4610       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4611         cells.push_back(i);
4612       cell2DinS2.clear();
4613     }
4614 }
4615
4616 /*!
4617  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4618  *
4619  * 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.
4620  * 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.
4621  * 
4622  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4623  * This convex envelop is computed using Jarvis march algorithm.
4624  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4625  * 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)
4626  * 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.
4627  *
4628  * \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.
4629  * \sa MEDCouplingUMesh::colinearize2D
4630  */
4631 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4632 {
4633   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4634     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4635   checkFullyDefined();
4636   const double *coords=getCoords()->getConstPointer();
4637   int nbOfCells=getNumberOfCells();
4638   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4639   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4640   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4641   int *workIndexOut=nodalConnecIndexOut->getPointer();
4642   *workIndexOut=0;
4643   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4644   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4645   std::set<INTERP_KERNEL::NormalizedCellType> types;
4646   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4647   isChanged->alloc(0,1);
4648   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4649     {
4650       int pos=nodalConnecOut->getNumberOfTuples();
4651       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4652         isChanged->pushBackSilent(i);
4653       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4654       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4655     }
4656   if(isChanged->empty())
4657     return 0;
4658   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4659   _types=types;
4660   return isChanged.retn();
4661 }
4662
4663 /*!
4664  * This method is \b NOT const because it can modify \a this.
4665  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4666  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4667  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4668  * \b 1 for translation and rotation around point of 'mesh1D'.
4669  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4670  */
4671 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4672 {
4673   checkFullyDefined();
4674   mesh1D->checkFullyDefined();
4675   if(!mesh1D->isContiguous1D())
4676     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4677   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4678     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4679   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4680     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4681   if(mesh1D->getMeshDimension()!=1)
4682     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4683   bool isQuad=false;
4684   if(isPresenceOfQuadratic())
4685     {
4686       if(mesh1D->isFullyQuadratic())
4687         isQuad=true;
4688       else
4689         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4690     }
4691   int oldNbOfNodes(getNumberOfNodes());
4692   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4693   switch(policy)
4694   {
4695     case 0:
4696       {
4697         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4698         break;
4699       }
4700     case 1:
4701       {
4702         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4703         break;
4704       }
4705     default:
4706       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4707   }
4708   setCoords(newCoords);
4709   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4710   updateTime();
4711   return ret.retn();
4712 }
4713
4714 /*!
4715  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4716  * If it is not the case an exception will be thrown.
4717  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4718  * intersection of plane defined by ('origin','vec').
4719  * This method has one in/out parameter : 'cut3DCurve'.
4720  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4721  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4722  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4723  * This method will throw an exception if \a this contains a non linear segment.
4724  */
4725 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4726 {
4727   checkFullyDefined();
4728   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4729     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4730   int ncells=getNumberOfCells();
4731   int nnodes=getNumberOfNodes();
4732   double vec2[3],vec3[3],vec4[3];
4733   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4734   if(normm<1e-6)
4735     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4736   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4737   const int *conn=_nodal_connec->getConstPointer();
4738   const int *connI=_nodal_connec_index->getConstPointer();
4739   const double *coo=_coords->getConstPointer();
4740   std::vector<double> addCoo;
4741   for(int i=0;i<ncells;i++)
4742     {
4743       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4744         {
4745           if(cut3DCurve[i]==-2)
4746             {
4747               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4748               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];
4749               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4750               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4751               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4752                 {
4753                   const double *st2=coo+3*st;
4754                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4755                   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]));
4756                   if(pos>eps && pos<1-eps)
4757                     {
4758                       int nNode=((int)addCoo.size())/3;
4759                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4760                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4761                       cut3DCurve[i]=nnodes+nNode;
4762                     }
4763                 }
4764             }
4765         }
4766       else
4767         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4768     }
4769   if(!addCoo.empty())
4770     {
4771       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4772       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4773       coo2->alloc(newNbOfNodes,3);
4774       double *tmp=coo2->getPointer();
4775       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4776       std::copy(addCoo.begin(),addCoo.end(),tmp);
4777       DataArrayDouble::SetArrayIn(coo2,_coords);
4778     }
4779 }
4780
4781 /*!
4782  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4783  * \param mesh1D is the input 1D mesh used for translation computation.
4784  * \return newCoords new coords filled by this method. 
4785  */
4786 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4787 {
4788   int oldNbOfNodes=getNumberOfNodes();
4789   int nbOf1DCells=mesh1D->getNumberOfCells();
4790   int spaceDim=getSpaceDimension();
4791   DataArrayDouble *ret=DataArrayDouble::New();
4792   std::vector<bool> isQuads;
4793   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4794   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4795   double *retPtr=ret->getPointer();
4796   const double *coords=getCoords()->getConstPointer();
4797   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4798   std::vector<int> v;
4799   std::vector<double> c;
4800   double vec[3];
4801   v.reserve(3);
4802   c.reserve(6);
4803   for(int i=0;i<nbOf1DCells;i++)
4804     {
4805       v.resize(0);
4806       mesh1D->getNodeIdsOfCell(i,v);
4807       c.resize(0);
4808       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4809       mesh1D->getCoordinatesOfNode(v[0],c);
4810       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4811       for(int j=0;j<oldNbOfNodes;j++)
4812         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4813       if(isQuad)
4814         {
4815           c.resize(0);
4816           mesh1D->getCoordinatesOfNode(v[1],c);
4817           mesh1D->getCoordinatesOfNode(v[0],c);
4818           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4819           for(int j=0;j<oldNbOfNodes;j++)
4820             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4821         }
4822     }
4823   ret->copyStringInfoFrom(*getCoords());
4824   return ret;
4825 }
4826
4827 /*!
4828  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4829  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4830  * \return newCoords new coords filled by this method. 
4831  */
4832 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4833 {
4834   if(mesh1D->getSpaceDimension()==2)
4835     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4836   if(mesh1D->getSpaceDimension()==3)
4837     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4838   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4839 }
4840
4841 /*!
4842  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4843  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4844  * \return newCoords new coords filled by this method. 
4845  */
4846 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4847 {
4848   if(isQuad)
4849     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4850   int oldNbOfNodes=getNumberOfNodes();
4851   int nbOf1DCells=mesh1D->getNumberOfCells();
4852   if(nbOf1DCells<2)
4853     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4854   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4855   int nbOfLevsInVec=nbOf1DCells+1;
4856   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4857   double *retPtr=ret->getPointer();
4858   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4859   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4860   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4861   tmp->setCoords(tmp2);
4862   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4863   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4864   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4865   for(int i=1;i<nbOfLevsInVec;i++)
4866     {
4867       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4868       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4869       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4870       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4871       tmp->translate(vec);
4872       double tmp3[2],radius,alpha,alpha0;
4873       const double *p0=i+1<nbOfLevsInVec?begin:third;
4874       const double *p1=i+1<nbOfLevsInVec?end:begin;
4875       const double *p2=i+1<nbOfLevsInVec?third:end;
4876       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4877       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]);
4878       double angle=acos(cosangle/(radius*radius));
4879       tmp->rotate(end,0,angle);
4880       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4881     }
4882   return ret.retn();
4883 }
4884
4885 /*!
4886  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4887  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4888  * \return newCoords new coords filled by this method. 
4889  */
4890 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4891 {
4892   if(isQuad)
4893     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4894   int oldNbOfNodes=getNumberOfNodes();
4895   int nbOf1DCells=mesh1D->getNumberOfCells();
4896   if(nbOf1DCells<2)
4897     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4898   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4899   int nbOfLevsInVec=nbOf1DCells+1;
4900   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4901   double *retPtr=ret->getPointer();
4902   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4903   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4904   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4905   tmp->setCoords(tmp2);
4906   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4907   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4908   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4909   for(int i=1;i<nbOfLevsInVec;i++)
4910     {
4911       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4912       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4913       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4914       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4915       tmp->translate(vec);
4916       double tmp3[2],radius,alpha,alpha0;
4917       const double *p0=i+1<nbOfLevsInVec?begin:third;
4918       const double *p1=i+1<nbOfLevsInVec?end:begin;
4919       const double *p2=i+1<nbOfLevsInVec?third:end;
4920       double vecPlane[3]={
4921         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4922         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4923         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4924       };
4925       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4926       if(norm>1.e-7)
4927         {
4928           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4929           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4930           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4931           double s2=norm2;
4932           double c2=cos(asin(s2));
4933           double m[3][3]={
4934             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4935             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4936             {-vec2[1]*s2, vec2[0]*s2, c2}
4937           };
4938           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]};
4939           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]};
4940           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]};
4941           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4942           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]);
4943           double angle=acos(cosangle/(radius*radius));
4944           tmp->rotate(end,vecPlane,angle);
4945         }
4946       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4947     }
4948   return ret.retn();
4949 }
4950
4951 /*!
4952  * This method is private because not easy to use for end user. This method is const contrary to
4953  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4954  * the coords sorted slice by slice.
4955  * \param isQuad specifies presence of quadratic cells.
4956  */
4957 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4958 {
4959   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4960   int nbOf2DCells(getNumberOfCells());
4961   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4962   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4963   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4964   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4965   newConnI->alloc(nbOf3DCells+1,1);
4966   int *newConnIPtr(newConnI->getPointer());
4967   *newConnIPtr++=0;
4968   std::vector<int> newc;
4969   for(int j=0;j<nbOf2DCells;j++)
4970     {
4971       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4972       *newConnIPtr++=(int)newc.size();
4973     }
4974   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4975   int *newConnPtr(newConn->getPointer());
4976   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4977   newConnIPtr=newConnI->getPointer();
4978   for(int iz=0;iz<nbOf1DCells;iz++)
4979     {
4980       if(iz!=0)
4981         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4982       const int *posOfTypeOfCell(newConnIPtr);
4983       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4984         {
4985           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4986           if(icell!=*posOfTypeOfCell)
4987             {
4988               if(*iter!=-1)
4989                 *newConnPtr=(*iter)+iz*deltaPerLev;
4990               else
4991                 *newConnPtr=-1;
4992             }
4993           else
4994             {
4995               *newConnPtr=*iter;
4996               posOfTypeOfCell++;
4997             }
4998         }
4999     }
5000   ret->setConnectivity(newConn,newConnI,true);
5001   ret->setCoords(getCoords());
5002   return ret;
5003 }
5004
5005 /*!
5006  * Checks if \a this mesh is constituted by only quadratic cells.
5007  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
5008  *  \throw If the coordinates array is not set.
5009  *  \throw If the nodal connectivity of cells is not defined.
5010  */
5011 bool MEDCouplingUMesh::isFullyQuadratic() const
5012 {
5013   checkFullyDefined();
5014   bool ret=true;
5015   int nbOfCells=getNumberOfCells();
5016   for(int i=0;i<nbOfCells && ret;i++)
5017     {
5018       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5019       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5020       ret=cm.isQuadratic();
5021     }
5022   return ret;
5023 }
5024
5025 /*!
5026  * Checks if \a this mesh includes any quadratic cell.
5027  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5028  *  \throw If the coordinates array is not set.
5029  *  \throw If the nodal connectivity of cells is not defined.
5030  */
5031 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5032 {
5033   checkFullyDefined();
5034   bool ret=false;
5035   int nbOfCells=getNumberOfCells();
5036   for(int i=0;i<nbOfCells && !ret;i++)
5037     {
5038       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5039       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5040       ret=cm.isQuadratic();
5041     }
5042   return ret;
5043 }
5044
5045 /*!
5046  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5047  * this mesh, it remains unchanged.
5048  *  \throw If the coordinates array is not set.
5049  *  \throw If the nodal connectivity of cells is not defined.
5050  */
5051 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5052 {
5053   checkFullyDefined();
5054   int nbOfCells=getNumberOfCells();
5055   int delta=0;
5056   const int *iciptr=_nodal_connec_index->getConstPointer();
5057   for(int i=0;i<nbOfCells;i++)
5058     {
5059       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5060       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5061       if(cm.isQuadratic())
5062         {
5063           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5064           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5065           if(!cml.isDynamic())
5066             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5067           else
5068             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5069         }
5070     }
5071   if(delta==0)
5072     return ;
5073   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5074   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5075   const int *icptr=_nodal_connec->getConstPointer();
5076   newConn->alloc(getMeshLength()-delta,1);
5077   newConnI->alloc(nbOfCells+1,1);
5078   int *ocptr=newConn->getPointer();
5079   int *ociptr=newConnI->getPointer();
5080   *ociptr=0;
5081   _types.clear();
5082   for(int i=0;i<nbOfCells;i++,ociptr++)
5083     {
5084       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5085       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5086       if(!cm.isQuadratic())
5087         {
5088           _types.insert(type);
5089           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5090           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5091         }
5092       else
5093         {
5094           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5095           _types.insert(typel);
5096           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5097           int newNbOfNodes=cml.getNumberOfNodes();
5098           if(cml.isDynamic())
5099             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5100           *ocptr++=(int)typel;
5101           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5102           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5103         }
5104     }
5105   setConnectivity(newConn,newConnI,false);
5106 }
5107
5108 /*!
5109  * This method converts all linear cell in \a this to quadratic one.
5110  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5111  * 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)
5112  * 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.
5113  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5114  * end of the existing coordinates.
5115  * 
5116  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5117  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5118  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5119  * 
5120  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5121  *
5122  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5123  */
5124 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5125 {
5126   DataArrayInt *conn=0,*connI=0;
5127   DataArrayDouble *coords=0;
5128   std::set<INTERP_KERNEL::NormalizedCellType> types;
5129   checkFullyDefined();
5130   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5131   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5132   int meshDim=getMeshDimension();
5133   switch(conversionType)
5134   {
5135     case 0:
5136       switch(meshDim)
5137       {
5138         case 1:
5139           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5140           connSafe=conn; connISafe=connI; coordsSafe=coords;
5141           break;
5142         case 2:
5143           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5144           connSafe=conn; connISafe=connI; coordsSafe=coords;
5145           break;
5146         case 3:
5147           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5148           connSafe=conn; connISafe=connI; coordsSafe=coords;
5149           break;
5150         default:
5151           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5152       }
5153       break;
5154         case 1:
5155           {
5156             switch(meshDim)
5157             {
5158               case 1:
5159                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5160                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5161                 break;
5162               case 2:
5163                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5164                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5165                 break;
5166               case 3:
5167                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5168                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5169                 break;
5170               default:
5171                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5172             }
5173             break;
5174           }
5175         default:
5176           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5177   }
5178   setConnectivity(connSafe,connISafe,false);
5179   _types=types;
5180   setCoords(coordsSafe);
5181   return ret.retn();
5182 }
5183
5184 #if 0
5185 /*!
5186  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5187  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5188  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5189  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5190  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5191  * This method can be seen as the opposite method of colinearize2D.
5192  * 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
5193  * to avoid to modify the numbering of existing nodes.
5194  *
5195  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5196  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5197  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5198  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5199  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5200  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5201  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5202  *
5203  * \sa buildDescendingConnectivity2
5204  */
5205 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5206                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5207 {
5208   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5209     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5210   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5211   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5212     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5213   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5214     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5215   //DataArrayInt *out0(0),*outi0(0);
5216   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5217   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5218   //out0s=out0s->buildUnique(); out0s->sort(true);
5219 }
5220 #endif
5221
5222 /*!
5223  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5224  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5225  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5226  */
5227 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5228 {
5229   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5230   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5231   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5232   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5233   int nbOfCells=getNumberOfCells();
5234   int nbOfNodes=getNumberOfNodes();
5235   const int *cPtr=_nodal_connec->getConstPointer();
5236   const int *icPtr=_nodal_connec_index->getConstPointer();
5237   int lastVal=0,offset=nbOfNodes;
5238   for(int i=0;i<nbOfCells;i++,icPtr++)
5239     {
5240       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5241       if(type==INTERP_KERNEL::NORM_SEG2)
5242         {
5243           types.insert(INTERP_KERNEL::NORM_SEG3);
5244           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5245           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5246           newConn->pushBackSilent(offset++);
5247           lastVal+=4;
5248           newConnI->pushBackSilent(lastVal);
5249           ret->pushBackSilent(i);
5250         }
5251       else
5252         {
5253           types.insert(type);
5254           lastVal+=(icPtr[1]-icPtr[0]);
5255           newConnI->pushBackSilent(lastVal);
5256           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5257         }
5258     }
5259   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5260   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5261   return ret.retn();
5262 }
5263
5264 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
5265 {
5266   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5267   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5268   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5269   //
5270   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5271   DataArrayInt *conn1D=0,*conn1DI=0;
5272   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5273   DataArrayDouble *coordsTmp=0;
5274   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5275   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5276   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5277   const int *c1DPtr=conn1D->begin();
5278   const int *c1DIPtr=conn1DI->begin();
5279   int nbOfCells=getNumberOfCells();
5280   const int *cPtr=_nodal_connec->getConstPointer();
5281   const int *icPtr=_nodal_connec_index->getConstPointer();
5282   int lastVal=0;
5283   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5284     {
5285       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5286       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5287       if(!cm.isQuadratic())
5288         {
5289           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5290           types.insert(typ2); newConn->pushBackSilent(typ2);
5291           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5292           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5293             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5294           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5295           newConnI->pushBackSilent(lastVal);
5296           ret->pushBackSilent(i);
5297         }
5298       else
5299         {
5300           types.insert(typ);
5301           lastVal+=(icPtr[1]-icPtr[0]);
5302           newConnI->pushBackSilent(lastVal);
5303           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5304         }
5305     }
5306   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5307   return ret.retn();
5308 }
5309
5310 /*!
5311  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5312  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5313  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5314  */
5315 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5316 {
5317   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5318   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5319   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5320 }
5321
5322 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5323 {
5324   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5325   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5326   //
5327   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5328   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5329   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5330   //
5331   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5332   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5333   DataArrayInt *conn1D=0,*conn1DI=0;
5334   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5335   DataArrayDouble *coordsTmp=0;
5336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5337   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5339   const int *c1DPtr=conn1D->begin();
5340   const int *c1DIPtr=conn1DI->begin();
5341   int nbOfCells=getNumberOfCells();
5342   const int *cPtr=_nodal_connec->getConstPointer();
5343   const int *icPtr=_nodal_connec_index->getConstPointer();
5344   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5345   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5346     {
5347       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5348       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5349       if(!cm.isQuadratic())
5350         {
5351           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5352           types.insert(typ2); newConn->pushBackSilent(typ2);
5353           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5354           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5355             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5356           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5357           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5358           newConnI->pushBackSilent(lastVal);
5359           ret->pushBackSilent(i);
5360         }
5361       else
5362         {
5363           types.insert(typ);
5364           lastVal+=(icPtr[1]-icPtr[0]);
5365           newConnI->pushBackSilent(lastVal);
5366           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5367         }
5368     }
5369   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5370   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5371   return ret.retn();
5372 }
5373
5374 /*!
5375  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5376  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5377  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5378  */
5379 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5380 {
5381   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5382   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5383   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5384 }
5385
5386 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5387 {
5388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5389   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5391   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5392   //
5393   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5394   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5395   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5396   //
5397   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5398   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5399   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5400   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5401   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5402   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5403   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5404   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5405   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5406   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5407   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5408   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5409   int nbOfCells=getNumberOfCells();
5410   const int *cPtr=_nodal_connec->getConstPointer();
5411   const int *icPtr=_nodal_connec_index->getConstPointer();
5412   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5413   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5414     {
5415       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5416       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5417       if(!cm.isQuadratic())
5418         {
5419           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5420           if(typ2==INTERP_KERNEL::NORM_ERROR)
5421             {
5422               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5423               throw INTERP_KERNEL::Exception(oss.str().c_str());
5424             }
5425           types.insert(typ2); newConn->pushBackSilent(typ2);
5426           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5427           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5428             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5429           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5430             {
5431               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5432               int tmpPos=newConn->getNumberOfTuples();
5433               newConn->pushBackSilent(nodeId2);
5434               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5435             }
5436           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5437           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5438           newConnI->pushBackSilent(lastVal);
5439           ret->pushBackSilent(i);
5440         }
5441       else
5442         {
5443           types.insert(typ);
5444           lastVal+=(icPtr[1]-icPtr[0]);
5445           newConnI->pushBackSilent(lastVal);
5446           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5447         }
5448     }
5449   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5450   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5451   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5452   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5453   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5454   int *c=newConn->getPointer();
5455   const int *cI(newConnI->begin());
5456   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5457     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5458   offset=coordsTmp2Safe->getNumberOfTuples();
5459   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5460     c[cI[(*elt)+1]-1]+=offset;
5461   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5462   return ret.retn();
5463 }
5464
5465 /*!
5466  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5467  * so that the number of cells remains the same. Quadratic faces are converted to
5468  * polygons. This method works only for 2D meshes in
5469  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5470  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5471  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5472  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5473  *         a polylinized edge constituting the input polygon.
5474  *  \throw If the coordinates array is not set.
5475  *  \throw If the nodal connectivity of cells is not defined.
5476  *  \throw If \a this->getMeshDimension() != 2.
5477  *  \throw If \a this->getSpaceDimension() != 2.
5478  */
5479 void MEDCouplingUMesh::tessellate2D(double eps)
5480 {
5481   checkFullyDefined();
5482   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5483     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5484   double epsa=fabs(eps);
5485   if(epsa<std::numeric_limits<double>::min())
5486     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 !");
5487   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5488   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5489   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5490   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5491   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5492   revDesc1=0; revDescIndx1=0;
5493   mDesc->tessellate2DCurve(eps);
5494   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5495   setCoords(mDesc->getCoords());
5496 }
5497
5498 /*!
5499  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5500  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5501  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5502  *         a sub-divided edge.
5503  *  \throw If the coordinates array is not set.
5504  *  \throw If the nodal connectivity of cells is not defined.
5505  *  \throw If \a this->getMeshDimension() != 1.
5506  *  \throw If \a this->getSpaceDimension() != 2.
5507  */
5508 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5509 {
5510   checkFullyDefined();
5511   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5512     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5513   double epsa=fabs(eps);
5514   if(epsa<std::numeric_limits<double>::min())
5515     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 !");
5516   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5517   int nbCells=getNumberOfCells();
5518   int nbNodes=getNumberOfNodes();
5519   const int *conn=_nodal_connec->getConstPointer();
5520   const int *connI=_nodal_connec_index->getConstPointer();
5521   const double *coords=_coords->getConstPointer();
5522   std::vector<double> addCoo;
5523   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5524   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5525   newConnI->alloc(nbCells+1,1);
5526   int *newConnIPtr=newConnI->getPointer();
5527   *newConnIPtr=0;
5528   int tmp1[3];
5529   INTERP_KERNEL::Node *tmp2[3];
5530   std::set<INTERP_KERNEL::NormalizedCellType> types;
5531   for(int i=0;i<nbCells;i++,newConnIPtr++)
5532     {
5533       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5534       if(cm.isQuadratic())
5535         {//assert(connI[i+1]-connI[i]-1==3)
5536           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5537           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5538           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5539           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5540           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5541           if(eac)
5542             {
5543               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5544               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5545               delete eac;
5546               newConnIPtr[1]=(int)newConn.size();
5547             }
5548           else
5549             {
5550               types.insert(INTERP_KERNEL::NORM_SEG2);
5551               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5552               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5553               newConnIPtr[1]=newConnIPtr[0]+3;
5554             }
5555         }
5556       else
5557         {
5558           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5559           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5560           newConnIPtr[1]=newConnIPtr[0]+3;
5561         }
5562     }
5563   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5564     return ;
5565   _types=types;
5566   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5567   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5568   newConnArr->alloc((int)newConn.size(),1);
5569   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5570   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5571   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5572   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5573   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5574   std::copy(addCoo.begin(),addCoo.end(),work);
5575   DataArrayDouble::SetArrayIn(newCoords,_coords);
5576   updateTime();
5577 }
5578
5579 /*!
5580  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5581  * In addition, returns an array mapping new cells to old ones. <br>
5582  * This method typically increases the number of cells in \a this mesh
5583  * but the number of nodes remains \b unchanged.
5584  * That's why the 3D splitting policies
5585  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5586  *  \param [in] policy - specifies a pattern used for splitting.
5587  * The semantic of \a policy is:
5588  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5589  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5590  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5591  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5592  *
5593  *
5594  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5595  *          an id of old cell producing it. The caller is to delete this array using
5596  *         decrRef() as it is no more needed.
5597  *
5598  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5599  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5600  *          and \a this->getMeshDimension() != 3. 
5601  *  \throw If \a policy is not one of the four discussed above.
5602  *  \throw If the nodal connectivity of cells is not defined.
5603  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5604  */
5605 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5606 {
5607   switch(policy)
5608   {
5609     case 0:
5610       return simplexizePol0();
5611     case 1:
5612       return simplexizePol1();
5613     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5614         return simplexizePlanarFace5();
5615     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5616         return simplexizePlanarFace6();
5617     default:
5618       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)");
5619   }
5620 }
5621
5622 /*!
5623  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5624  * - 1D: INTERP_KERNEL::NORM_SEG2
5625  * - 2D: INTERP_KERNEL::NORM_TRI3
5626  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5627  *
5628  * This method is useful for users that need to use P1 field services as
5629  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5630  * All these methods need mesh support containing only simplex cells.
5631  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5632  *  \throw If the coordinates array is not set.
5633  *  \throw If the nodal connectivity of cells is not defined.
5634  *  \throw If \a this->getMeshDimension() < 1.
5635  */
5636 bool MEDCouplingUMesh::areOnlySimplexCells() const
5637 {
5638   checkFullyDefined();
5639   int mdim=getMeshDimension();
5640   if(mdim<1 || mdim>3)
5641     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5642   int nbCells=getNumberOfCells();
5643   const int *conn=_nodal_connec->getConstPointer();
5644   const int *connI=_nodal_connec_index->getConstPointer();
5645   for(int i=0;i<nbCells;i++)
5646     {
5647       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5648       if(!cm.isSimplex())
5649         return false;
5650     }
5651   return true;
5652 }
5653
5654 /*!
5655  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5656  */
5657 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5658 {
5659   checkConnectivityFullyDefined();
5660   if(getMeshDimension()!=2)
5661     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5662   int nbOfCells=getNumberOfCells();
5663   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5664   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5665   ret->alloc(nbOfCells+nbOfCutCells,1);
5666   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5667   int *retPt=ret->getPointer();
5668   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5669   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5670   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5671   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5672   int *pt=newConn->getPointer();
5673   int *ptI=newConnI->getPointer();
5674   ptI[0]=0;
5675   const int *oldc=_nodal_connec->getConstPointer();
5676   const int *ci=_nodal_connec_index->getConstPointer();
5677   for(int i=0;i<nbOfCells;i++,ci++)
5678     {
5679       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5680         {
5681           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5682             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5683           pt=std::copy(tmp,tmp+8,pt);
5684           ptI[1]=ptI[0]+4;
5685           ptI[2]=ptI[0]+8;
5686           *retPt++=i;
5687           *retPt++=i;
5688           ptI+=2;
5689         }
5690       else
5691         {
5692           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5693           ptI[1]=ptI[0]+ci[1]-ci[0];
5694           ptI++;
5695           *retPt++=i;
5696         }
5697     }
5698   _nodal_connec->decrRef();
5699   _nodal_connec=newConn.retn();
5700   _nodal_connec_index->decrRef();
5701   _nodal_connec_index=newConnI.retn();
5702   computeTypes();
5703   updateTime();
5704   return ret.retn();
5705 }
5706
5707 /*!
5708  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5709  */
5710 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5711 {
5712   checkConnectivityFullyDefined();
5713   if(getMeshDimension()!=2)
5714     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5715   int nbOfCells=getNumberOfCells();
5716   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5717   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5718   ret->alloc(nbOfCells+nbOfCutCells,1);
5719   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5720   int *retPt=ret->getPointer();
5721   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5722   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5723   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5724   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5725   int *pt=newConn->getPointer();
5726   int *ptI=newConnI->getPointer();
5727   ptI[0]=0;
5728   const int *oldc=_nodal_connec->getConstPointer();
5729   const int *ci=_nodal_connec_index->getConstPointer();
5730   for(int i=0;i<nbOfCells;i++,ci++)
5731     {
5732       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5733         {
5734           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5735             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5736           pt=std::copy(tmp,tmp+8,pt);
5737           ptI[1]=ptI[0]+4;
5738           ptI[2]=ptI[0]+8;
5739           *retPt++=i;
5740           *retPt++=i;
5741           ptI+=2;
5742         }
5743       else
5744         {
5745           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5746           ptI[1]=ptI[0]+ci[1]-ci[0];
5747           ptI++;
5748           *retPt++=i;
5749         }
5750     }
5751   _nodal_connec->decrRef();
5752   _nodal_connec=newConn.retn();
5753   _nodal_connec_index->decrRef();
5754   _nodal_connec_index=newConnI.retn();
5755   computeTypes();
5756   updateTime();
5757   return ret.retn();
5758 }
5759
5760 /*!
5761  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5762  */
5763 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5764 {
5765   checkConnectivityFullyDefined();
5766   if(getMeshDimension()!=3)
5767     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5768   int nbOfCells=getNumberOfCells();
5769   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5770   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5771   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5772   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5773   int *retPt=ret->getPointer();
5774   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5775   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5776   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5777   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5778   int *pt=newConn->getPointer();
5779   int *ptI=newConnI->getPointer();
5780   ptI[0]=0;
5781   const int *oldc=_nodal_connec->getConstPointer();
5782   const int *ci=_nodal_connec_index->getConstPointer();
5783   for(int i=0;i<nbOfCells;i++,ci++)
5784     {
5785       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5786         {
5787           for(int j=0;j<5;j++,pt+=5,ptI++)
5788             {
5789               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5790               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];
5791               *retPt++=i;
5792               ptI[1]=ptI[0]+5;
5793             }
5794         }
5795       else
5796         {
5797           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5798           ptI[1]=ptI[0]+ci[1]-ci[0];
5799           ptI++;
5800           *retPt++=i;
5801         }
5802     }
5803   _nodal_connec->decrRef();
5804   _nodal_connec=newConn.retn();
5805   _nodal_connec_index->decrRef();
5806   _nodal_connec_index=newConnI.retn();
5807   computeTypes();
5808   updateTime();
5809   return ret.retn();
5810 }
5811
5812 /*!
5813  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5814  */
5815 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5816 {
5817   checkConnectivityFullyDefined();
5818   if(getMeshDimension()!=3)
5819     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5820   int nbOfCells=getNumberOfCells();
5821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5822   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5823   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5824   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5825   int *retPt=ret->getPointer();
5826   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5827   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5828   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5829   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5830   int *pt=newConn->getPointer();
5831   int *ptI=newConnI->getPointer();
5832   ptI[0]=0;
5833   const int *oldc=_nodal_connec->getConstPointer();
5834   const int *ci=_nodal_connec_index->getConstPointer();
5835   for(int i=0;i<nbOfCells;i++,ci++)
5836     {
5837       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5838         {
5839           for(int j=0;j<6;j++,pt+=5,ptI++)
5840             {
5841               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5842               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];
5843               *retPt++=i;
5844               ptI[1]=ptI[0]+5;
5845             }
5846         }
5847       else
5848         {
5849           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5850           ptI[1]=ptI[0]+ci[1]-ci[0];
5851           ptI++;
5852           *retPt++=i;
5853         }
5854     }
5855   _nodal_connec->decrRef();
5856   _nodal_connec=newConn.retn();
5857   _nodal_connec_index->decrRef();
5858   _nodal_connec_index=newConnI.retn();
5859   computeTypes();
5860   updateTime();
5861   return ret.retn();
5862 }
5863
5864 /*!
5865  * 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.
5866  * This method completly ignore coordinates.
5867  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5868  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5869  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5870  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5871  */
5872 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5873 {
5874   checkFullyDefined();
5875   if(getMeshDimension()!=2)
5876     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5877   int nbOfCells=getNumberOfCells();
5878   int *connI=_nodal_connec_index->getPointer();
5879   int newConnLgth=0;
5880   for(int i=0;i<nbOfCells;i++,connI++)
5881     {
5882       int offset=descIndex[i];
5883       int nbOfEdges=descIndex[i+1]-offset;
5884       //
5885       bool ddirect=desc[offset+nbOfEdges-1]>0;
5886       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5887       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5888       for(int j=0;j<nbOfEdges;j++)
5889         {
5890           bool direct=desc[offset+j]>0;
5891           int edgeId=std::abs(desc[offset+j])-1;
5892           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5893             {
5894               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5895               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5896               int ref2=direct?id1:id2;
5897               if(ref==ref2)
5898                 {
5899                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5900                   newConnLgth+=nbOfSubNodes-1;
5901                   ref=direct?id2:id1;
5902                 }
5903               else
5904                 {
5905                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5906                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5907                 }
5908             }
5909           else
5910             {
5911               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5912             }
5913         }
5914       newConnLgth++;//+1 is for cell type
5915       connI[1]=newConnLgth;
5916     }
5917   //
5918   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5919   newConn->alloc(newConnLgth,1);
5920   int *work=newConn->getPointer();
5921   for(int i=0;i<nbOfCells;i++)
5922     {
5923       *work++=INTERP_KERNEL::NORM_POLYGON;
5924       int offset=descIndex[i];
5925       int nbOfEdges=descIndex[i+1]-offset;
5926       for(int j=0;j<nbOfEdges;j++)
5927         {
5928           bool direct=desc[offset+j]>0;
5929           int edgeId=std::abs(desc[offset+j])-1;
5930           if(direct)
5931             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5932           else
5933             {
5934               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5935               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5936               work=std::copy(it,it+nbOfSubNodes-1,work);
5937             }
5938         }
5939     }
5940   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5941   _types.clear();
5942   if(nbOfCells>0)
5943     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5944 }
5945
5946 /*!
5947  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5948  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5949  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5950  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5951  * so it can be useful to call mergeNodes() before calling this method.
5952  *  \throw If \a this->getMeshDimension() <= 1.
5953  *  \throw If the coordinates array is not set.
5954  *  \throw If the nodal connectivity of cells is not defined.
5955  */
5956 void MEDCouplingUMesh::convertDegeneratedCells()
5957 {
5958   checkFullyDefined();
5959   if(getMeshDimension()<=1)
5960     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5961   int nbOfCells=getNumberOfCells();
5962   if(nbOfCells<1)
5963     return ;
5964   int initMeshLgth=getMeshLength();
5965   int *conn=_nodal_connec->getPointer();
5966   int *index=_nodal_connec_index->getPointer();
5967   int posOfCurCell=0;
5968   int newPos=0;
5969   int lgthOfCurCell;
5970   for(int i=0;i<nbOfCells;i++)
5971     {
5972       lgthOfCurCell=index[i+1]-posOfCurCell;
5973       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5974       int newLgth;
5975       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5976                                                                                                      conn+newPos+1,newLgth);
5977       conn[newPos]=newType;
5978       newPos+=newLgth+1;
5979       posOfCurCell=index[i+1];
5980       index[i+1]=newPos;
5981     }
5982   if(newPos!=initMeshLgth)
5983     _nodal_connec->reAlloc(newPos);
5984   computeTypes();
5985 }
5986
5987 /*!
5988  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5989  * A cell is considered to be oriented correctly if an angle between its
5990  * normal vector and a given vector is less than \c PI / \c 2.
5991  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5992  *         cells. 
5993  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5994  *         checked.
5995  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5996  *         is not cleared before filling in.
5997  *  \throw If \a this->getMeshDimension() != 2.
5998  *  \throw If \a this->getSpaceDimension() != 3.
5999  *
6000  *  \if ENABLE_EXAMPLES
6001  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6002  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6003  *  \endif
6004  */
6005 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6006 {
6007   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6008     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6009   int nbOfCells=getNumberOfCells();
6010   const int *conn=_nodal_connec->getConstPointer();
6011   const int *connI=_nodal_connec_index->getConstPointer();
6012   const double *coordsPtr=_coords->getConstPointer();
6013   for(int i=0;i<nbOfCells;i++)
6014     {
6015       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6016       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6017         {
6018           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6019           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6020             cells.push_back(i);
6021         }
6022     }
6023 }
6024
6025 /*!
6026  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6027  * considered to be oriented correctly if an angle between its normal vector and a
6028  * given vector is less than \c PI / \c 2. 
6029  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6030  *         cells. 
6031  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6032  *         checked.
6033  *  \throw If \a this->getMeshDimension() != 2.
6034  *  \throw If \a this->getSpaceDimension() != 3.
6035  *
6036  *  \if ENABLE_EXAMPLES
6037  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6038  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6039  *  \endif
6040  *
6041  *  \sa changeOrientationOfCells
6042  */
6043 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6044 {
6045   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6046     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6047   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6048   const int *connI(_nodal_connec_index->getConstPointer());
6049   const double *coordsPtr(_coords->getConstPointer());
6050   bool isModified(false);
6051   for(int i=0;i<nbOfCells;i++)
6052     {
6053       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6054       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6055         {
6056           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6057           bool isQuadratic(cm.isQuadratic());
6058           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6059             {
6060               isModified=true;
6061               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6062             }
6063         }
6064     }
6065   if(isModified)
6066     _nodal_connec->declareAsNew();
6067   updateTime();
6068 }
6069
6070 /*!
6071  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6072  *
6073  * \sa orientCorrectly2DCells
6074  */
6075 void MEDCouplingUMesh::changeOrientationOfCells()
6076 {
6077   int mdim(getMeshDimension());
6078   if(mdim!=2 && mdim!=1)
6079     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6080   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6081   const int *connI(_nodal_connec_index->getConstPointer());
6082   if(mdim==2)
6083     {//2D
6084       for(int i=0;i<nbOfCells;i++)
6085         {
6086           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6087           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6088           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6089         }
6090     }
6091   else
6092     {//1D
6093       for(int i=0;i<nbOfCells;i++)
6094         {
6095           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6096           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6097           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6098         }
6099     }
6100 }
6101
6102 /*!
6103  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6104  * oriented facets. The normal vector of the facet should point out of the cell.
6105  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6106  *         is not cleared before filling in.
6107  *  \throw If \a this->getMeshDimension() != 3.
6108  *  \throw If \a this->getSpaceDimension() != 3.
6109  *  \throw If the coordinates array is not set.
6110  *  \throw If the nodal connectivity of cells is not defined.
6111  *
6112  *  \if ENABLE_EXAMPLES
6113  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6114  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6115  *  \endif
6116  */
6117 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6118 {
6119   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6120     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6121   int nbOfCells=getNumberOfCells();
6122   const int *conn=_nodal_connec->getConstPointer();
6123   const int *connI=_nodal_connec_index->getConstPointer();
6124   const double *coordsPtr=_coords->getConstPointer();
6125   for(int i=0;i<nbOfCells;i++)
6126     {
6127       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6128       if(type==INTERP_KERNEL::NORM_POLYHED)
6129         {
6130           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6131             cells.push_back(i);
6132         }
6133     }
6134 }
6135
6136 /*!
6137  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6138  * out of the cell. 
6139  *  \throw If \a this->getMeshDimension() != 3.
6140  *  \throw If \a this->getSpaceDimension() != 3.
6141  *  \throw If the coordinates array is not set.
6142  *  \throw If the nodal connectivity of cells is not defined.
6143  *  \throw If the reparation fails.
6144  *
6145  *  \if ENABLE_EXAMPLES
6146  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6147  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6148  *  \endif
6149  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6150  */
6151 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6152 {
6153   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6154     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6155   int nbOfCells=getNumberOfCells();
6156   int *conn=_nodal_connec->getPointer();
6157   const int *connI=_nodal_connec_index->getConstPointer();
6158   const double *coordsPtr=_coords->getConstPointer();
6159   for(int i=0;i<nbOfCells;i++)
6160     {
6161       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6162       if(type==INTERP_KERNEL::NORM_POLYHED)
6163         {
6164           try
6165           {
6166               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6167                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6168           }
6169           catch(INTERP_KERNEL::Exception& e)
6170           {
6171               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6172               throw INTERP_KERNEL::Exception(oss.str().c_str());
6173           }
6174         }
6175     }
6176   updateTime();
6177 }
6178
6179 /*!
6180  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6181  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6182  * according to which the first facet of the cell should be oriented to have the normal vector
6183  * pointing out of cell.
6184  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6185  *         cells. The caller is to delete this array using decrRef() as it is no more
6186  *         needed. 
6187  *  \throw If \a this->getMeshDimension() != 3.
6188  *  \throw If \a this->getSpaceDimension() != 3.
6189  *  \throw If the coordinates array is not set.
6190  *  \throw If the nodal connectivity of cells is not defined.
6191  *
6192  *  \if ENABLE_EXAMPLES
6193  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6194  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6195  *  \endif
6196  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6197  */
6198 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6199 {
6200   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6201   if(getMeshDimension()!=3)
6202     throw INTERP_KERNEL::Exception(msg);
6203   int spaceDim=getSpaceDimension();
6204   if(spaceDim!=3)
6205     throw INTERP_KERNEL::Exception(msg);
6206   //
6207   int nbOfCells=getNumberOfCells();
6208   int *conn=_nodal_connec->getPointer();
6209   const int *connI=_nodal_connec_index->getConstPointer();
6210   const double *coo=getCoords()->getConstPointer();
6211   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6212   for(int i=0;i<nbOfCells;i++)
6213     {
6214       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6215       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6216         {
6217           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6218             {
6219               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6220               cells->pushBackSilent(i);
6221             }
6222         }
6223     }
6224   return cells.retn();
6225 }
6226
6227 /*!
6228  * This method is a faster method to correct orientation of all 3D cells in \a this.
6229  * 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.
6230  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6231  * 
6232  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6233  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6234  */
6235 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6236 {
6237   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6238     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6239   int nbOfCells=getNumberOfCells();
6240   int *conn=_nodal_connec->getPointer();
6241   const int *connI=_nodal_connec_index->getConstPointer();
6242   const double *coordsPtr=_coords->getConstPointer();
6243   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6244   for(int i=0;i<nbOfCells;i++)
6245     {
6246       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6247       switch(type)
6248       {
6249         case INTERP_KERNEL::NORM_TETRA4:
6250           {
6251             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6252               {
6253                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6254                 ret->pushBackSilent(i);
6255               }
6256             break;
6257           }
6258         case INTERP_KERNEL::NORM_PYRA5:
6259           {
6260             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6261               {
6262                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6263                 ret->pushBackSilent(i);
6264               }
6265             break;
6266           }
6267         case INTERP_KERNEL::NORM_PENTA6:
6268         case INTERP_KERNEL::NORM_HEXA8:
6269         case INTERP_KERNEL::NORM_HEXGP12:
6270           {
6271             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6272               {
6273                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6274                 ret->pushBackSilent(i);
6275               }
6276             break;
6277           }
6278         case INTERP_KERNEL::NORM_POLYHED:
6279           {
6280             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6281               {
6282                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6283                 ret->pushBackSilent(i);
6284               }
6285             break;
6286           }
6287         default:
6288           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 !");
6289       }
6290     }
6291   updateTime();
6292   return ret.retn();
6293 }
6294
6295 /*!
6296  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6297  * If it is not the case an exception will be thrown.
6298  * This method is fast because the first cell of \a this is used to compute the plane.
6299  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6300  * \param pos output of size at least 3 used to store a point owned of searched plane.
6301  */
6302 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6303 {
6304   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6305     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6306   const int *conn=_nodal_connec->getConstPointer();
6307   const int *connI=_nodal_connec_index->getConstPointer();
6308   const double *coordsPtr=_coords->getConstPointer();
6309   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6310   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6311 }
6312
6313 /*!
6314  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6315  * cells. Currently cells of the following types are treated:
6316  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6317  * For a cell of other type an exception is thrown.
6318  * Space dimension of a 2D mesh can be either 2 or 3.
6319  * The Edge Ratio of a cell \f$t\f$ is: 
6320  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6321  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6322  *  the smallest edge lengths of \f$t\f$.
6323  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6324  *          cells and one time, lying on \a this mesh. The caller is to delete this
6325  *          field using decrRef() as it is no more needed. 
6326  *  \throw If the coordinates array is not set.
6327  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6328  *  \throw If the connectivity data array has more than one component.
6329  *  \throw If the connectivity data array has a named component.
6330  *  \throw If the connectivity index data array has more than one component.
6331  *  \throw If the connectivity index data array has a named component.
6332  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6333  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6334  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6335  */
6336 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6337 {
6338   checkCoherency();
6339   int spaceDim=getSpaceDimension();
6340   int meshDim=getMeshDimension();
6341   if(spaceDim!=2 && spaceDim!=3)
6342     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6343   if(meshDim!=2 && meshDim!=3)
6344     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6345   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6346   ret->setMesh(this);
6347   int nbOfCells=getNumberOfCells();
6348   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6349   arr->alloc(nbOfCells,1);
6350   double *pt=arr->getPointer();
6351   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6352   const int *conn=_nodal_connec->getConstPointer();
6353   const int *connI=_nodal_connec_index->getConstPointer();
6354   const double *coo=_coords->getConstPointer();
6355   double tmp[12];
6356   for(int i=0;i<nbOfCells;i++,pt++)
6357     {
6358       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6359       switch(t)
6360       {
6361         case INTERP_KERNEL::NORM_TRI3:
6362           {
6363             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6364             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6365             break;
6366           }
6367         case INTERP_KERNEL::NORM_QUAD4:
6368           {
6369             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6370             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6371             break;
6372           }
6373         case INTERP_KERNEL::NORM_TETRA4:
6374           {
6375             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6376             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6377             break;
6378           }
6379         default:
6380           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6381       }
6382       conn+=connI[i+1]-connI[i];
6383     }
6384   ret->setName("EdgeRatio");
6385   ret->synchronizeTimeWithSupport();
6386   return ret.retn();
6387 }
6388
6389 /*!
6390  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6391  * cells. Currently cells of the following types are treated:
6392  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6393  * For a cell of other type an exception is thrown.
6394  * Space dimension of a 2D mesh can be either 2 or 3.
6395  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6396  *          cells and one time, lying on \a this mesh. The caller is to delete this
6397  *          field using decrRef() as it is no more needed. 
6398  *  \throw If the coordinates array is not set.
6399  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6400  *  \throw If the connectivity data array has more than one component.
6401  *  \throw If the connectivity data array has a named component.
6402  *  \throw If the connectivity index data array has more than one component.
6403  *  \throw If the connectivity index data array has a named component.
6404  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6405  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6406  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6407  */
6408 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6409 {
6410   checkCoherency();
6411   int spaceDim=getSpaceDimension();
6412   int meshDim=getMeshDimension();
6413   if(spaceDim!=2 && spaceDim!=3)
6414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6415   if(meshDim!=2 && meshDim!=3)
6416     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6417   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6418   ret->setMesh(this);
6419   int nbOfCells=getNumberOfCells();
6420   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6421   arr->alloc(nbOfCells,1);
6422   double *pt=arr->getPointer();
6423   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6424   const int *conn=_nodal_connec->getConstPointer();
6425   const int *connI=_nodal_connec_index->getConstPointer();
6426   const double *coo=_coords->getConstPointer();
6427   double tmp[12];
6428   for(int i=0;i<nbOfCells;i++,pt++)
6429     {
6430       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6431       switch(t)
6432       {
6433         case INTERP_KERNEL::NORM_TRI3:
6434           {
6435             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6436             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6437             break;
6438           }
6439         case INTERP_KERNEL::NORM_QUAD4:
6440           {
6441             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6442             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6443             break;
6444           }
6445         case INTERP_KERNEL::NORM_TETRA4:
6446           {
6447             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6448             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6449             break;
6450           }
6451         default:
6452           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6453       }
6454       conn+=connI[i+1]-connI[i];
6455     }
6456   ret->setName("AspectRatio");
6457   ret->synchronizeTimeWithSupport();
6458   return ret.retn();
6459 }
6460
6461 /*!
6462  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6463  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6464  * treated: INTERP_KERNEL::NORM_QUAD4.
6465  * For a cell of other type an exception is thrown.
6466  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6467  *          cells and one time, lying on \a this mesh. The caller is to delete this
6468  *          field using decrRef() as it is no more needed. 
6469  *  \throw If the coordinates array is not set.
6470  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6471  *  \throw If the connectivity data array has more than one component.
6472  *  \throw If the connectivity data array has a named component.
6473  *  \throw If the connectivity index data array has more than one component.
6474  *  \throw If the connectivity index data array has a named component.
6475  *  \throw If \a this->getMeshDimension() != 2.
6476  *  \throw If \a this->getSpaceDimension() != 3.
6477  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6478  */
6479 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6480 {
6481   checkCoherency();
6482   int spaceDim=getSpaceDimension();
6483   int meshDim=getMeshDimension();
6484   if(spaceDim!=3)
6485     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6486   if(meshDim!=2)
6487     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6488   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6489   ret->setMesh(this);
6490   int nbOfCells=getNumberOfCells();
6491   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6492   arr->alloc(nbOfCells,1);
6493   double *pt=arr->getPointer();
6494   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6495   const int *conn=_nodal_connec->getConstPointer();
6496   const int *connI=_nodal_connec_index->getConstPointer();
6497   const double *coo=_coords->getConstPointer();
6498   double tmp[12];
6499   for(int i=0;i<nbOfCells;i++,pt++)
6500     {
6501       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6502       switch(t)
6503       {
6504         case INTERP_KERNEL::NORM_QUAD4:
6505           {
6506             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6507             *pt=INTERP_KERNEL::quadWarp(tmp);
6508             break;
6509           }
6510         default:
6511           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6512       }
6513       conn+=connI[i+1]-connI[i];
6514     }
6515   ret->setName("Warp");
6516   ret->synchronizeTimeWithSupport();
6517   return ret.retn();
6518 }
6519
6520
6521 /*!
6522  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6523  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6524  * treated: INTERP_KERNEL::NORM_QUAD4.
6525  * For a cell of other type an exception is thrown.
6526  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6527  *          cells and one time, lying on \a this mesh. The caller is to delete this
6528  *          field using decrRef() as it is no more needed. 
6529  *  \throw If the coordinates array is not set.
6530  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6531  *  \throw If the connectivity data array has more than one component.
6532  *  \throw If the connectivity data array has a named component.
6533  *  \throw If the connectivity index data array has more than one component.
6534  *  \throw If the connectivity index data array has a named component.
6535  *  \throw If \a this->getMeshDimension() != 2.
6536  *  \throw If \a this->getSpaceDimension() != 3.
6537  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6538  */
6539 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6540 {
6541   checkCoherency();
6542   int spaceDim=getSpaceDimension();
6543   int meshDim=getMeshDimension();
6544   if(spaceDim!=3)
6545     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6546   if(meshDim!=2)
6547     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6548   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6549   ret->setMesh(this);
6550   int nbOfCells=getNumberOfCells();
6551   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6552   arr->alloc(nbOfCells,1);
6553   double *pt=arr->getPointer();
6554   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6555   const int *conn=_nodal_connec->getConstPointer();
6556   const int *connI=_nodal_connec_index->getConstPointer();
6557   const double *coo=_coords->getConstPointer();
6558   double tmp[12];
6559   for(int i=0;i<nbOfCells;i++,pt++)
6560     {
6561       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6562       switch(t)
6563       {
6564         case INTERP_KERNEL::NORM_QUAD4:
6565           {
6566             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6567             *pt=INTERP_KERNEL::quadSkew(tmp);
6568             break;
6569           }
6570         default:
6571           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6572       }
6573       conn+=connI[i+1]-connI[i];
6574     }
6575   ret->setName("Skew");
6576   ret->synchronizeTimeWithSupport();
6577   return ret.retn();
6578 }
6579
6580 /*!
6581  * 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.
6582  *
6583  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6584  *
6585  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6586  */
6587 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6588 {
6589   checkCoherency();
6590   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6591   ret->setMesh(this);
6592   std::set<INTERP_KERNEL::NormalizedCellType> types;
6593   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6594   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6595   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6596   arr->alloc(nbCells,1);
6597   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6598     {
6599       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6600       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6601       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6602     }
6603   ret->setArray(arr);
6604   ret->setName("Diameter");
6605   return ret.retn();
6606 }
6607
6608 /*!
6609  * This method aggregate the bbox of each cell and put it into bbox parameter.
6610  * 
6611  * \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)
6612  *                         For all other cases this input parameter is ignored.
6613  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6614  * 
6615  * \throw If \a this is not fully set (coordinates and connectivity).
6616  * \throw If a cell in \a this has no valid nodeId.
6617  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6618  */
6619 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6620 {
6621   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6622   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.
6623     return getBoundingBoxForBBTreeFast();
6624   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6625     {
6626       bool presenceOfQuadratic(false);
6627       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6628         {
6629           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6630           if(cm.isQuadratic())
6631             presenceOfQuadratic=true;
6632         }
6633       if(!presenceOfQuadratic)
6634         return getBoundingBoxForBBTreeFast();
6635       if(mDim==2 && sDim==2)
6636         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6637       else
6638         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6639     }
6640   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) !");
6641 }
6642
6643 /*!
6644  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6645  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6646  * 
6647  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6648  * 
6649  * \throw If \a this is not fully set (coordinates and connectivity).
6650  * \throw If a cell in \a this has no valid nodeId.
6651  */
6652 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6653 {
6654   checkFullyDefined();
6655   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6656   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6657   double *bbox(ret->getPointer());
6658   for(int i=0;i<nbOfCells*spaceDim;i++)
6659     {
6660       bbox[2*i]=std::numeric_limits<double>::max();
6661       bbox[2*i+1]=-std::numeric_limits<double>::max();
6662     }
6663   const double *coordsPtr(_coords->getConstPointer());
6664   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6665   for(int i=0;i<nbOfCells;i++)
6666     {
6667       int offset=connI[i]+1;
6668       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6669       for(int j=0;j<nbOfNodesForCell;j++)
6670         {
6671           int nodeId=conn[offset+j];
6672           if(nodeId>=0 && nodeId<nbOfNodes)
6673             {
6674               for(int k=0;k<spaceDim;k++)
6675                 {
6676                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6677                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6678                 }
6679               kk++;
6680             }
6681         }
6682       if(kk==0)
6683         {
6684           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6685           throw INTERP_KERNEL::Exception(oss.str().c_str());
6686         }
6687     }
6688   return ret.retn();
6689 }
6690
6691 /*!
6692  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6693  * useful for 2D meshes having quadratic cells
6694  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6695  * the two extremities of the arc of circle).
6696  * 
6697  * \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)
6698  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6699  * \throw If \a this is not fully defined.
6700  * \throw If \a this is not a mesh with meshDimension equal to 2.
6701  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6702  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6703  */
6704 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6705 {
6706   checkFullyDefined();
6707   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6708   if(spaceDim!=2 || mDim!=2)
6709     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!");
6710   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6711   double *bbox(ret->getPointer());
6712   const double *coords(_coords->getConstPointer());
6713   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6714   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6715     {
6716       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6717       int sz(connI[1]-connI[0]-1);
6718       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6719       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6720       INTERP_KERNEL::QuadraticPolygon *pol(0);
6721       for(int j=0;j<sz;j++)
6722         {
6723           int nodeId(conn[*connI+1+j]);
6724           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6725         }
6726       if(!cm.isQuadratic())
6727         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6728       else
6729         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6730       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6731       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6732     }
6733   return ret.retn();
6734 }
6735
6736 /*!
6737  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6738  * useful for 2D meshes having quadratic cells
6739  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6740  * the two extremities of the arc of circle).
6741  * 
6742  * \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)
6743  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6744  * \throw If \a this is not fully defined.
6745  * \throw If \a this is not a mesh with meshDimension equal to 1.
6746  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6747  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6748  */
6749 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6750 {
6751   checkFullyDefined();
6752   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6753   if(spaceDim!=2 || mDim!=1)
6754     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!");
6755   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6756   double *bbox(ret->getPointer());
6757   const double *coords(_coords->getConstPointer());
6758   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6759   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6760     {
6761       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6762       int sz(connI[1]-connI[0]-1);
6763       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6764       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6765       INTERP_KERNEL::Edge *edge(0);
6766       for(int j=0;j<sz;j++)
6767         {
6768           int nodeId(conn[*connI+1+j]);
6769           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6770         }
6771       if(!cm.isQuadratic())
6772         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6773       else
6774         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6775       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6776       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6777     }
6778   return ret.retn();
6779 }
6780
6781 /// @cond INTERNAL
6782
6783 namespace ParaMEDMEMImpl
6784 {
6785   class ConnReader
6786   {
6787   public:
6788     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6789     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6790   private:
6791     const int *_conn;
6792     int _val;
6793   };
6794
6795   class ConnReader2
6796   {
6797   public:
6798     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6799     bool operator() (const int& pos) { return _conn[pos]==_val; }
6800   private:
6801     const int *_conn;
6802     int _val;
6803   };
6804 }
6805
6806 /// @endcond
6807
6808 /*!
6809  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6810  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6811  * \a this is composed in cell types.
6812  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6813  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6814  * This parameter is kept only for compatibility with other methode listed above.
6815  */
6816 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6817 {
6818   checkConnectivityFullyDefined();
6819   const int *conn=_nodal_connec->getConstPointer();
6820   const int *connI=_nodal_connec_index->getConstPointer();
6821   const int *work=connI;
6822   int nbOfCells=getNumberOfCells();
6823   std::size_t n=getAllGeoTypes().size();
6824   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6825   std::set<INTERP_KERNEL::NormalizedCellType> types;
6826   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6827     {
6828       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6829       if(types.find(typ)!=types.end())
6830         {
6831           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6832           oss << " is not contiguous !";
6833           throw INTERP_KERNEL::Exception(oss.str().c_str());
6834         }
6835       types.insert(typ);
6836       ret[3*i]=typ;
6837       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6838       ret[3*i+1]=(int)std::distance(work,work2);
6839       work=work2;
6840     }
6841   return ret;
6842 }
6843
6844 /*!
6845  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6846  * only for types cell, type node is not managed.
6847  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6848  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6849  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6850  * If 2 or more same geometric type is in \a code and exception is thrown too.
6851  *
6852  * This method firstly checks
6853  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6854  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6855  * an exception is thrown too.
6856  * 
6857  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6858  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6859  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6860  */
6861 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6862 {
6863   if(code.empty())
6864     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6865   std::size_t sz=code.size();
6866   std::size_t n=sz/3;
6867   if(sz%3!=0)
6868     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6869   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6870   int nb=0;
6871   bool isNoPflUsed=true;
6872   for(std::size_t i=0;i<n;i++)
6873     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6874       {
6875         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6876         nb+=code[3*i+1];
6877         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6878           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6879         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6880       }
6881   if(types.size()!=n)
6882     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6883   if(isNoPflUsed)
6884     {
6885       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6886         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6887       if(types.size()==_types.size())
6888         return 0;
6889     }
6890   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6891   ret->alloc(nb,1);
6892   int *retPtr=ret->getPointer();
6893   const int *connI=_nodal_connec_index->getConstPointer();
6894   const int *conn=_nodal_connec->getConstPointer();
6895   int nbOfCells=getNumberOfCells();
6896   const int *i=connI;
6897   int kk=0;
6898   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6899     {
6900       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6901       int offset=(int)std::distance(connI,i);
6902       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6903       int nbOfCellsOfCurType=(int)std::distance(i,j);
6904       if(code[3*kk+2]==-1)
6905         for(int k=0;k<nbOfCellsOfCurType;k++)
6906           *retPtr++=k+offset;
6907       else
6908         {
6909           int idInIdsPerType=code[3*kk+2];
6910           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6911             {
6912               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6913               if(zePfl)
6914                 {
6915                   zePfl->checkAllocated();
6916                   if(zePfl->getNumberOfComponents()==1)
6917                     {
6918                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6919                         {
6920                           if(*k>=0 && *k<nbOfCellsOfCurType)
6921                             *retPtr=(*k)+offset;
6922                           else
6923                             {
6924                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6925                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6926                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6927                             }
6928                         }
6929                     }
6930                   else
6931                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6932                 }
6933               else
6934                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6935             }
6936           else
6937             {
6938               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6939               oss << " should be in [0," << idsPerType.size() << ") !";
6940               throw INTERP_KERNEL::Exception(oss.str().c_str());
6941             }
6942         }
6943       i=j;
6944     }
6945   return ret.retn();
6946 }
6947
6948 /*!
6949  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
6950  * 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.
6951  * 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.
6952  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6953  * 
6954  * \param [in] profile
6955  * \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.
6956  * \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,
6957  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6958  * \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.
6959  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6960  * \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
6961  */
6962 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6963 {
6964   if(!profile)
6965     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6966   if(profile->getNumberOfComponents()!=1)
6967     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6968   checkConnectivityFullyDefined();
6969   const int *conn=_nodal_connec->getConstPointer();
6970   const int *connI=_nodal_connec_index->getConstPointer();
6971   int nbOfCells=getNumberOfCells();
6972   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6973   std::vector<int> typeRangeVals(1);
6974   for(const int *i=connI;i!=connI+nbOfCells;)
6975     {
6976       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6977       if(std::find(types.begin(),types.end(),curType)!=types.end())
6978         {
6979           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6980         }
6981       types.push_back(curType);
6982       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6983       typeRangeVals.push_back((int)std::distance(connI,i));
6984     }
6985   //
6986   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6987   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6988   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6989   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6990   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6991   //
6992   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6993   code.resize(3*nbOfCastsFinal);
6994   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6995   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6996   for(int i=0;i<nbOfCastsFinal;i++)
6997     {
6998       int castId=castsPresent->getIJ(i,0);
6999       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
7000       idsInPflPerType2.push_back(tmp3);
7001       code[3*i]=(int)types[castId];
7002       code[3*i+1]=tmp3->getNumberOfTuples();
7003       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
7004       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
7005         {
7006           tmp4->copyStringInfoFrom(*profile);
7007           idsPerType2.push_back(tmp4);
7008           code[3*i+2]=(int)idsPerType2.size()-1;
7009         }
7010       else
7011         {
7012           code[3*i+2]=-1;
7013         }
7014     }
7015   std::size_t sz2=idsInPflPerType2.size();
7016   idsInPflPerType.resize(sz2);
7017   for(std::size_t i=0;i<sz2;i++)
7018     {
7019       DataArrayInt *locDa=idsInPflPerType2[i];
7020       locDa->incrRef();
7021       idsInPflPerType[i]=locDa;
7022     }
7023   std::size_t sz=idsPerType2.size();
7024   idsPerType.resize(sz);
7025   for(std::size_t i=0;i<sz;i++)
7026     {
7027       DataArrayInt *locDa=idsPerType2[i];
7028       locDa->incrRef();
7029       idsPerType[i]=locDa;
7030     }
7031 }
7032
7033 /*!
7034  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7035  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7036  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7037  * 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.
7038  */
7039 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7040 {
7041   checkFullyDefined();
7042   nM1LevMesh->checkFullyDefined();
7043   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7044     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7045   if(_coords!=nM1LevMesh->getCoords())
7046     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7047   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
7048   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
7049   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7050   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7051   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7052   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7053   tmp->setConnectivity(tmp0,tmp1);
7054   tmp->renumberCells(ret0->getConstPointer(),false);
7055   revDesc=tmp->getNodalConnectivity();
7056   revDescIndx=tmp->getNodalConnectivityIndex();
7057   DataArrayInt *ret=0;
7058   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7059     {
7060       int tmp2;
7061       ret->getMaxValue(tmp2);
7062       ret->decrRef();
7063       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7064       throw INTERP_KERNEL::Exception(oss.str().c_str());
7065     }
7066   nM1LevMeshIds=ret;
7067   //
7068   revDesc->incrRef();
7069   revDescIndx->incrRef();
7070   ret1->incrRef();
7071   ret0->incrRef();
7072   meshnM1Old2New=ret0;
7073   return ret1;
7074 }
7075
7076 /*!
7077  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7078  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7079  * in "Old to New" mode.
7080  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7081  *          this array using decrRef() as it is no more needed.
7082  *  \throw If the nodal connectivity of cells is not defined.
7083  */
7084 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7085 {
7086   checkConnectivityFullyDefined();
7087   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7088   renumberCells(ret->getConstPointer(),false);
7089   return ret.retn();
7090 }
7091
7092 /*!
7093  * This methods checks that cells are sorted by their types.
7094  * This method makes asumption (no check) that connectivity is correctly set before calling.
7095  */
7096 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7097 {
7098   checkFullyDefined();
7099   const int *conn=_nodal_connec->getConstPointer();
7100   const int *connI=_nodal_connec_index->getConstPointer();
7101   int nbOfCells=getNumberOfCells();
7102   std::set<INTERP_KERNEL::NormalizedCellType> types;
7103   for(const int *i=connI;i!=connI+nbOfCells;)
7104     {
7105       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7106       if(types.find(curType)!=types.end())
7107         return false;
7108       types.insert(curType);
7109       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7110     }
7111   return true;
7112 }
7113
7114 /*!
7115  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7116  * The geometric type order is specified by MED file.
7117  * 
7118  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7119  */
7120 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7121 {
7122   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7123 }
7124
7125 /*!
7126  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7127  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7128  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7129  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7130  */
7131 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7132 {
7133   checkFullyDefined();
7134   const int *conn=_nodal_connec->getConstPointer();
7135   const int *connI=_nodal_connec_index->getConstPointer();
7136   int nbOfCells=getNumberOfCells();
7137   if(nbOfCells==0)
7138     return true;
7139   int lastPos=-1;
7140   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7141   for(const int *i=connI;i!=connI+nbOfCells;)
7142     {
7143       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7144       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7145       if(isTypeExists!=orderEnd)
7146         {
7147           int pos=(int)std::distance(orderBg,isTypeExists);
7148           if(pos<=lastPos)
7149             return false;
7150           lastPos=pos;
7151           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7152         }
7153       else
7154         {
7155           if(sg.find(curType)==sg.end())
7156             {
7157               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7158               sg.insert(curType);
7159             }
7160           else
7161             return false;
7162         }
7163     }
7164   return true;
7165 }
7166
7167 /*!
7168  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7169  * 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
7170  * 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'.
7171  */
7172 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7173 {
7174   checkConnectivityFullyDefined();
7175   int nbOfCells=getNumberOfCells();
7176   const int *conn=_nodal_connec->getConstPointer();
7177   const int *connI=_nodal_connec_index->getConstPointer();
7178   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7179   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7180   tmpa->alloc(nbOfCells,1);
7181   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7182   tmpb->fillWithZero();
7183   int *tmp=tmpa->getPointer();
7184   int *tmp2=tmpb->getPointer();
7185   for(const int *i=connI;i!=connI+nbOfCells;i++)
7186     {
7187       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7188       if(where!=orderEnd)
7189         {
7190           int pos=(int)std::distance(orderBg,where);
7191           tmp2[pos]++;
7192           tmp[std::distance(connI,i)]=pos;
7193         }
7194       else
7195         {
7196           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7197           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7198           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7199           throw INTERP_KERNEL::Exception(oss.str().c_str());
7200         }
7201     }
7202   nbPerType=tmpb.retn();
7203   return tmpa.retn();
7204 }
7205
7206 /*!
7207  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7208  *
7209  * \return a new object containing the old to new correspondance.
7210  *
7211  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7212  */
7213 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7214 {
7215   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7216 }
7217
7218 /*!
7219  * 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.
7220  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7221  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7222  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7223  */
7224 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7225 {
7226   DataArrayInt *nbPerType=0;
7227   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7228   nbPerType->decrRef();
7229   return tmpa->buildPermArrPerLevel();
7230 }
7231
7232 /*!
7233  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7234  * The number of cells remains unchanged after the call of this method.
7235  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7236  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7237  *
7238  * \return the array giving the correspondance old to new.
7239  */
7240 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7241 {
7242   checkFullyDefined();
7243   computeTypes();
7244   const int *conn=_nodal_connec->getConstPointer();
7245   const int *connI=_nodal_connec_index->getConstPointer();
7246   int nbOfCells=getNumberOfCells();
7247   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7248   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7249     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7250       {
7251         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7252         types.push_back(curType);
7253         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7254       }
7255   DataArrayInt *ret=DataArrayInt::New();
7256   ret->alloc(nbOfCells,1);
7257   int *retPtr=ret->getPointer();
7258   std::fill(retPtr,retPtr+nbOfCells,-1);
7259   int newCellId=0;
7260   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7261     {
7262       for(const int *i=connI;i!=connI+nbOfCells;i++)
7263         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7264           retPtr[std::distance(connI,i)]=newCellId++;
7265     }
7266   renumberCells(retPtr,false);
7267   return ret;
7268 }
7269
7270 /*!
7271  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7272  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7273  * This method makes asumption that connectivity is correctly set before calling.
7274  */
7275 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7276 {
7277   checkConnectivityFullyDefined();
7278   const int *conn=_nodal_connec->getConstPointer();
7279   const int *connI=_nodal_connec_index->getConstPointer();
7280   int nbOfCells=getNumberOfCells();
7281   std::vector<MEDCouplingUMesh *> ret;
7282   for(const int *i=connI;i!=connI+nbOfCells;)
7283     {
7284       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7285       int beginCellId=(int)std::distance(connI,i);
7286       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7287       int endCellId=(int)std::distance(connI,i);
7288       int sz=endCellId-beginCellId;
7289       int *cells=new int[sz];
7290       for(int j=0;j<sz;j++)
7291         cells[j]=beginCellId+j;
7292       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7293       delete [] cells;
7294       ret.push_back(m);
7295     }
7296   return ret;
7297 }
7298
7299 /*!
7300  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7301  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7302  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7303  *
7304  * \return a newly allocated instance, that the caller must manage.
7305  * \throw If \a this contains more than one geometric type.
7306  * \throw If the nodal connectivity of \a this is not fully defined.
7307  * \throw If the internal data is not coherent.
7308  */
7309 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7310 {
7311   checkConnectivityFullyDefined();
7312   if(_types.size()!=1)
7313     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7314   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7315   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7316   ret->setCoords(getCoords());
7317   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7318   if(retC)
7319     {
7320       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7321       retC->setNodalConnectivity(c);
7322     }
7323   else
7324     {
7325       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7326       if(!retD)
7327         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7328       DataArrayInt *c=0,*ci=0;
7329       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7330       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7331       retD->setNodalConnectivity(cs,cis);
7332     }
7333   return ret.retn();
7334 }
7335
7336 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7337 {
7338   checkConnectivityFullyDefined();
7339   if(_types.size()!=1)
7340     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7341   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7342   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7343   if(cm.isDynamic())
7344     {
7345       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7346       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7347       throw INTERP_KERNEL::Exception(oss.str().c_str());
7348     }
7349   int nbCells=getNumberOfCells();
7350   int typi=(int)typ;
7351   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7352   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7353   int *outPtr=connOut->getPointer();
7354   const int *conn=_nodal_connec->begin();
7355   const int *connI=_nodal_connec_index->begin();
7356   nbNodesPerCell++;
7357   for(int i=0;i<nbCells;i++,connI++)
7358     {
7359       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7360         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7361       else
7362         {
7363           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 << ") !";
7364           throw INTERP_KERNEL::Exception(oss.str().c_str());
7365         }
7366     }
7367   return connOut.retn();
7368 }
7369
7370 /*!
7371  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7372  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7373  * \param nodalConn
7374  * \param nodalConnI
7375  */
7376 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7377 {
7378   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7379   checkConnectivityFullyDefined();
7380   if(_types.size()!=1)
7381     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7382   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7383   if(lgth<nbCells)
7384     throw INTERP_KERNEL::Exception(msg0);
7385   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7386   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7387   int *cp(c->getPointer()),*cip(ci->getPointer());
7388   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7389   cip[0]=0;
7390   for(int i=0;i<nbCells;i++,cip++,incip++)
7391     {
7392       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7393       int delta(stop-strt);
7394       if(delta>=1)
7395         {
7396           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7397             cp=std::copy(incp+strt,incp+stop,cp);
7398           else
7399             throw INTERP_KERNEL::Exception(msg0);
7400         }
7401       else
7402         throw INTERP_KERNEL::Exception(msg0);
7403       cip[1]=cip[0]+delta;
7404     }
7405   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7406 }
7407
7408 /*!
7409  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7410  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7411  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7412  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7413  * are not used here to avoid the build of big permutation array.
7414  *
7415  * \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
7416  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7417  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7418  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7419  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7420  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7421  * \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
7422  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7423  */
7424 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7425                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7426                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7427 {
7428   std::vector<const MEDCouplingUMesh *> ms2;
7429   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7430     if(*it)
7431       {
7432         (*it)->checkConnectivityFullyDefined();
7433         ms2.push_back(*it);
7434       }
7435   if(ms2.empty())
7436     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7437   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7438   int meshDim=ms2[0]->getMeshDimension();
7439   std::vector<const MEDCouplingUMesh *> m1ssm;
7440   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7441   //
7442   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7443   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7444   int fake=0,rk=0;
7445   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7446   ret1->alloc(0,1); ret2->alloc(0,1);
7447   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7448     {
7449       if(meshDim!=(*it)->getMeshDimension())
7450         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7451       if(refCoo!=(*it)->getCoords())
7452         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7453       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7454       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7455       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7456       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7457         {
7458           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7459           m1ssmSingleAuto.push_back(singleCell);
7460           m1ssmSingle.push_back(singleCell);
7461           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7462         }
7463     }
7464   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7465   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7466   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7467   for(std::size_t i=0;i<m1ssm.size();i++)
7468     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7469   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7470   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7471   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7472   return ret0.retn();
7473 }
7474
7475 /*!
7476  * This method returns a newly created DataArrayInt instance.
7477  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7478  */
7479 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7480 {
7481   checkFullyDefined();
7482   const int *conn=_nodal_connec->getConstPointer();
7483   const int *connIndex=_nodal_connec_index->getConstPointer();
7484   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7485   for(const int *w=begin;w!=end;w++)
7486     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7487       ret->pushBackSilent(*w);
7488   return ret.retn();
7489 }
7490
7491 /*!
7492  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7493  * are in [0:getNumberOfCells())
7494  */
7495 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7496 {
7497   checkFullyDefined();
7498   const int *conn=_nodal_connec->getConstPointer();
7499   const int *connI=_nodal_connec_index->getConstPointer();
7500   int nbOfCells=getNumberOfCells();
7501   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7502   int *tmp=new int[nbOfCells];
7503   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7504     {
7505       int j=0;
7506       for(const int *i=connI;i!=connI+nbOfCells;i++)
7507         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7508           tmp[std::distance(connI,i)]=j++;
7509     }
7510   DataArrayInt *ret=DataArrayInt::New();
7511   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7512   ret->copyStringInfoFrom(*da);
7513   int *retPtr=ret->getPointer();
7514   const int *daPtr=da->getConstPointer();
7515   int nbOfElems=da->getNbOfElems();
7516   for(int k=0;k<nbOfElems;k++)
7517     retPtr[k]=tmp[daPtr[k]];
7518   delete [] tmp;
7519   return ret;
7520 }
7521
7522 /*!
7523  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7524  * This method \b works \b for mesh sorted by type.
7525  * cells whose ids is in 'idsPerGeoType' array.
7526  * This method conserves coords and name of mesh.
7527  */
7528 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7529 {
7530   std::vector<int> code=getDistributionOfTypes();
7531   std::size_t nOfTypesInThis=code.size()/3;
7532   int sz=0,szOfType=0;
7533   for(std::size_t i=0;i<nOfTypesInThis;i++)
7534     {
7535       if(code[3*i]!=type)
7536         sz+=code[3*i+1];
7537       else
7538         szOfType=code[3*i+1];
7539     }
7540   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7541     if(*work<0 || *work>=szOfType)
7542       {
7543         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7544         oss << ". It should be in [0," << szOfType << ") !";
7545         throw INTERP_KERNEL::Exception(oss.str().c_str());
7546       }
7547   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7548   int *idsPtr=idsTokeep->getPointer();
7549   int offset=0;
7550   for(std::size_t i=0;i<nOfTypesInThis;i++)
7551     {
7552       if(code[3*i]!=type)
7553         for(int j=0;j<code[3*i+1];j++)
7554           *idsPtr++=offset+j;
7555       else
7556         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7557       offset+=code[3*i+1];
7558     }
7559   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7560   ret->copyTinyInfoFrom(this);
7561   return ret.retn();
7562 }
7563
7564 /*!
7565  * This method returns a vector of size 'this->getNumberOfCells()'.
7566  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7567  */
7568 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7569 {
7570   int ncell=getNumberOfCells();
7571   std::vector<bool> ret(ncell);
7572   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7573   const int *c=getNodalConnectivity()->getConstPointer();
7574   for(int i=0;i<ncell;i++)
7575     {
7576       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7577       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7578       ret[i]=cm.isQuadratic();
7579     }
7580   return ret;
7581 }
7582
7583 /*!
7584  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7585  */
7586 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7587 {
7588   if(other->getType()!=UNSTRUCTURED)
7589     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7590   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7591   return MergeUMeshes(this,otherC);
7592 }
7593
7594 /*!
7595  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7596  * computed by averaging coordinates of cell nodes, so this method is not a right
7597  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7598  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7599  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7600  *          components. The caller is to delete this array using decrRef() as it is
7601  *          no more needed.
7602  *  \throw If the coordinates array is not set.
7603  *  \throw If the nodal connectivity of cells is not defined.
7604  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7605  */
7606 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7607 {
7608   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7609   int spaceDim=getSpaceDimension();
7610   int nbOfCells=getNumberOfCells();
7611   ret->alloc(nbOfCells,spaceDim);
7612   ret->copyStringInfoFrom(*getCoords());
7613   double *ptToFill=ret->getPointer();
7614   const int *nodal=_nodal_connec->getConstPointer();
7615   const int *nodalI=_nodal_connec_index->getConstPointer();
7616   const double *coor=_coords->getConstPointer();
7617   for(int i=0;i<nbOfCells;i++)
7618     {
7619       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7620       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7621       ptToFill+=spaceDim;
7622     }
7623   return ret.retn();
7624 }
7625
7626 /*!
7627  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7628  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7629  * 
7630  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7631  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7632  * 
7633  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7634  * \throw If \a this is not fully defined (coordinates and connectivity)
7635  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7636  */
7637 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7638 {
7639   checkFullyDefined();
7640   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7641   int spaceDim=getSpaceDimension();
7642   int nbOfCells=getNumberOfCells();
7643   int nbOfNodes=getNumberOfNodes();
7644   ret->alloc(nbOfCells,spaceDim);
7645   double *ptToFill=ret->getPointer();
7646   const int *nodal=_nodal_connec->getConstPointer();
7647   const int *nodalI=_nodal_connec_index->getConstPointer();
7648   const double *coor=_coords->getConstPointer();
7649   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7650     {
7651       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7652       std::fill(ptToFill,ptToFill+spaceDim,0.);
7653       if(type!=INTERP_KERNEL::NORM_POLYHED)
7654         {
7655           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7656             {
7657               if(*conn>=0 && *conn<nbOfNodes)
7658                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7659               else
7660                 {
7661                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7662                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7663                 }
7664             }
7665           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7666           if(nbOfNodesInCell>0)
7667             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7668           else
7669             {
7670               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7671               throw INTERP_KERNEL::Exception(oss.str().c_str());
7672             }
7673         }
7674       else
7675         {
7676           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7677           s.erase(-1);
7678           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7679             {
7680               if(*it>=0 && *it<nbOfNodes)
7681                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7682               else
7683                 {
7684                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7685                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7686                 }
7687             }
7688           if(!s.empty())
7689             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7690           else
7691             {
7692               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7693               throw INTERP_KERNEL::Exception(oss.str().c_str());
7694             }
7695         }
7696     }
7697   return ret.retn();
7698 }
7699
7700 /*!
7701  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7702  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7703  * are specified via an array of cell ids. 
7704  *  \warning Validity of the specified cell ids is not checked! 
7705  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7706  *  \param [in] begin - an array of cell ids of interest.
7707  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7708  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7709  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7710  *          caller is to delete this array using decrRef() as it is no more needed. 
7711  *  \throw If the coordinates array is not set.
7712  *  \throw If the nodal connectivity of cells is not defined.
7713  *
7714  *  \if ENABLE_EXAMPLES
7715  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7716  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7717  *  \endif
7718  */
7719 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7720 {
7721   DataArrayDouble *ret=DataArrayDouble::New();
7722   int spaceDim=getSpaceDimension();
7723   int nbOfTuple=(int)std::distance(begin,end);
7724   ret->alloc(nbOfTuple,spaceDim);
7725   double *ptToFill=ret->getPointer();
7726   double *tmp=new double[spaceDim];
7727   const int *nodal=_nodal_connec->getConstPointer();
7728   const int *nodalI=_nodal_connec_index->getConstPointer();
7729   const double *coor=_coords->getConstPointer();
7730   for(const int *w=begin;w!=end;w++)
7731     {
7732       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7733       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7734       ptToFill+=spaceDim;
7735     }
7736   delete [] tmp;
7737   return ret;
7738 }
7739
7740 /*!
7741  * 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".
7742  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7743  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7744  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7745  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7746  * 
7747  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7748  * \throw If spaceDim!=3 or meshDim!=2.
7749  * \throw If connectivity of \a this is invalid.
7750  * \throw If connectivity of a cell in \a this points to an invalid node.
7751  */
7752 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7753 {
7754   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7755   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7756   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7757     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7758   ret->alloc(nbOfCells,4);
7759   double *retPtr(ret->getPointer());
7760   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7761   const double *coor(_coords->begin());
7762   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7763     {
7764       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7765       if(nodalI[1]-nodalI[0]>=3)
7766         {
7767           for(int j=0;j<3;j++)
7768             {
7769               int nodeId(nodal[nodalI[0]+1+j]);
7770               if(nodeId>=0 && nodeId<nbOfNodes)
7771                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7772               else
7773                 {
7774                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7775                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7776                 }
7777             }
7778         }
7779       else
7780         {
7781           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7782           throw INTERP_KERNEL::Exception(oss.str().c_str());
7783         }
7784       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7785       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7786     }
7787   return ret.retn();
7788 }
7789
7790 /*!
7791  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7792  * 
7793  */
7794 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7795 {
7796   if(!da)
7797     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7798   da->checkAllocated();
7799   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7800   ret->setCoords(da);
7801   int nbOfTuples=da->getNumberOfTuples();
7802   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7803   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7804   c->alloc(2*nbOfTuples,1);
7805   cI->alloc(nbOfTuples+1,1);
7806   int *cp=c->getPointer();
7807   int *cip=cI->getPointer();
7808   *cip++=0;
7809   for(int i=0;i<nbOfTuples;i++)
7810     {
7811       *cp++=INTERP_KERNEL::NORM_POINT1;
7812       *cp++=i;
7813       *cip++=2*(i+1);
7814     }
7815   ret->setConnectivity(c,cI,true);
7816   return ret.retn();
7817 }
7818 /*!
7819  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7820  * Cells and nodes of
7821  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7822  *  \param [in] mesh1 - the first mesh.
7823  *  \param [in] mesh2 - the second mesh.
7824  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7825  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7826  *          is no more needed.
7827  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7828  *  \throw If the coordinates array is not set in none of the meshes.
7829  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7830  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7831  */
7832 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7833 {
7834   std::vector<const MEDCouplingUMesh *> tmp(2);
7835   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7836   return MergeUMeshes(tmp);
7837 }
7838
7839 /*!
7840  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7841  * Cells and nodes of
7842  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7843  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7844  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7845  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7846  *          is no more needed.
7847  *  \throw If \a a.size() == 0.
7848  *  \throw If \a a[ *i* ] == NULL.
7849  *  \throw If the coordinates array is not set in none of the meshes.
7850  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7851  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7852  */
7853 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7854 {
7855   std::size_t sz=a.size();
7856   if(sz==0)
7857     return MergeUMeshesLL(a);
7858   for(std::size_t ii=0;ii<sz;ii++)
7859     if(!a[ii])
7860       {
7861         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7862         throw INTERP_KERNEL::Exception(oss.str().c_str());
7863       }
7864   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7865   std::vector< const MEDCouplingUMesh * > aa(sz);
7866   int spaceDim=-3;
7867   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7868     {
7869       const MEDCouplingUMesh *cur=a[i];
7870       const DataArrayDouble *coo=cur->getCoords();
7871       if(coo)
7872         spaceDim=coo->getNumberOfComponents();
7873     }
7874   if(spaceDim==-3)
7875     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7876   for(std::size_t i=0;i<sz;i++)
7877     {
7878       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7879       aa[i]=bb[i];
7880     }
7881   return MergeUMeshesLL(aa);
7882 }
7883
7884 /// @cond INTERNAL
7885
7886 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7887 {
7888   if(a.empty())
7889     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7890   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7891   int meshDim=(*it)->getMeshDimension();
7892   int nbOfCells=(*it)->getNumberOfCells();
7893   int meshLgth=(*it++)->getMeshLength();
7894   for(;it!=a.end();it++)
7895     {
7896       if(meshDim!=(*it)->getMeshDimension())
7897         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7898       nbOfCells+=(*it)->getNumberOfCells();
7899       meshLgth+=(*it)->getMeshLength();
7900     }
7901   std::vector<const MEDCouplingPointSet *> aps(a.size());
7902   std::copy(a.begin(),a.end(),aps.begin());
7903   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7904   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7905   ret->setCoords(pts);
7906   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7907   c->alloc(meshLgth,1);
7908   int *cPtr=c->getPointer();
7909   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7910   cI->alloc(nbOfCells+1,1);
7911   int *cIPtr=cI->getPointer();
7912   *cIPtr++=0;
7913   int offset=0;
7914   int offset2=0;
7915   for(it=a.begin();it!=a.end();it++)
7916     {
7917       int curNbOfCell=(*it)->getNumberOfCells();
7918       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7919       const int *curC=(*it)->_nodal_connec->getConstPointer();
7920       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7921       for(int j=0;j<curNbOfCell;j++)
7922         {
7923           const int *src=curC+curCI[j];
7924           *cPtr++=*src++;
7925           for(;src!=curC+curCI[j+1];src++,cPtr++)
7926             {
7927               if(*src!=-1)
7928                 *cPtr=*src+offset2;
7929               else
7930                 *cPtr=-1;
7931             }
7932         }
7933       offset+=curCI[curNbOfCell];
7934       offset2+=(*it)->getNumberOfNodes();
7935     }
7936   //
7937   ret->setConnectivity(c,cI,true);
7938   return ret.retn();
7939 }
7940
7941 /// @endcond
7942
7943 /*!
7944  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7945  * dimension and sharing the node coordinates array.
7946  * All cells of the first mesh precede all cells of the second mesh
7947  * within the result mesh. 
7948  *  \param [in] mesh1 - the first mesh.
7949  *  \param [in] mesh2 - the second mesh.
7950  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7951  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7952  *          is no more needed.
7953  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7954  *  \throw If the meshes do not share the node coordinates array.
7955  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7956  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7957  */
7958 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7959 {
7960   std::vector<const MEDCouplingUMesh *> tmp(2);
7961   tmp[0]=mesh1; tmp[1]=mesh2;
7962   return MergeUMeshesOnSameCoords(tmp);
7963 }
7964
7965 /*!
7966  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7967  * dimension and sharing the node coordinates array.
7968  * All cells of the *i*-th mesh precede all cells of the
7969  * (*i*+1)-th mesh within the result mesh.
7970  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7971  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7972  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7973  *          is no more needed.
7974  *  \throw If \a a.size() == 0.
7975  *  \throw If \a a[ *i* ] == NULL.
7976  *  \throw If the meshes do not share the node coordinates array.
7977  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7978  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7979  */
7980 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7981 {
7982   if(meshes.empty())
7983     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7984   for(std::size_t ii=0;ii<meshes.size();ii++)
7985     if(!meshes[ii])
7986       {
7987         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7988         throw INTERP_KERNEL::Exception(oss.str().c_str());
7989       }
7990   const DataArrayDouble *coords=meshes.front()->getCoords();
7991   int meshDim=meshes.front()->getMeshDimension();
7992   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7993   int meshLgth=0;
7994   int meshIndexLgth=0;
7995   for(;iter!=meshes.end();iter++)
7996     {
7997       if(coords!=(*iter)->getCoords())
7998         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7999       if(meshDim!=(*iter)->getMeshDimension())
8000         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8001       meshLgth+=(*iter)->getMeshLength();
8002       meshIndexLgth+=(*iter)->getNumberOfCells();
8003     }
8004   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
8005   nodal->alloc(meshLgth,1);
8006   int *nodalPtr=nodal->getPointer();
8007   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
8008   nodalIndex->alloc(meshIndexLgth+1,1);
8009   int *nodalIndexPtr=nodalIndex->getPointer();
8010   int offset=0;
8011   for(iter=meshes.begin();iter!=meshes.end();iter++)
8012     {
8013       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
8014       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
8015       int nbOfCells=(*iter)->getNumberOfCells();
8016       int meshLgth2=(*iter)->getMeshLength();
8017       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8018       if(iter!=meshes.begin())
8019         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8020       else
8021         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8022       offset+=meshLgth2;
8023     }
8024   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8025   ret->setName("merge");
8026   ret->setMeshDimension(meshDim);
8027   ret->setConnectivity(nodal,nodalIndex,true);
8028   ret->setCoords(coords);
8029   return ret;
8030 }
8031
8032 /*!
8033  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8034  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8035  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8036  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8037  * New" mode are returned for each input mesh.
8038  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8039  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
8040  *          valid values [0,1,2], see zipConnectivityTraducer().
8041  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8042  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8043  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
8044  *          no more needed.
8045  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8046  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8047  *          is no more needed.
8048  *  \throw If \a meshes.size() == 0.
8049  *  \throw If \a meshes[ *i* ] == NULL.
8050  *  \throw If the meshes do not share the node coordinates array.
8051  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8052  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
8053  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8054  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
8055  */
8056 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8057 {
8058   //All checks are delegated to MergeUMeshesOnSameCoords
8059   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8060   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8061   corr.resize(meshes.size());
8062   std::size_t nbOfMeshes=meshes.size();
8063   int offset=0;
8064   const int *o2nPtr=o2n->getConstPointer();
8065   for(std::size_t i=0;i<nbOfMeshes;i++)
8066     {
8067       DataArrayInt *tmp=DataArrayInt::New();
8068       int curNbOfCells=meshes[i]->getNumberOfCells();
8069       tmp->alloc(curNbOfCells,1);
8070       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8071       offset+=curNbOfCells;
8072       tmp->setName(meshes[i]->getName());
8073       corr[i]=tmp;
8074     }
8075   return ret.retn();
8076 }
8077
8078 /*!
8079  * Makes all given meshes share the nodal connectivity array. The common connectivity
8080  * array is created by concatenating the connectivity arrays of all given meshes. All
8081  * the given meshes must be of the same space dimension but dimension of cells **can
8082  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8083  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8084  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8085  *  \param [in,out] meshes - a vector of meshes to update.
8086  *  \throw If any of \a meshes is NULL.
8087  *  \throw If the coordinates array is not set in any of \a meshes.
8088  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8089  *  \throw If \a meshes are of different space dimension.
8090  */
8091 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8092 {
8093   std::size_t sz=meshes.size();
8094   if(sz==0 || sz==1)
8095     return;
8096   std::vector< const DataArrayDouble * > coords(meshes.size());
8097   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8098   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8099     {
8100       if((*it))
8101         {
8102           (*it)->checkConnectivityFullyDefined();
8103           const DataArrayDouble *coo=(*it)->getCoords();
8104           if(coo)
8105             *it2=coo;
8106           else
8107             {
8108               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8109               oss << " has no coordinate array defined !";
8110               throw INTERP_KERNEL::Exception(oss.str().c_str());
8111             }
8112         }
8113       else
8114         {
8115           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8116           oss << " is null !";
8117           throw INTERP_KERNEL::Exception(oss.str().c_str());
8118         }
8119     }
8120   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8121   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8122   int offset=(*it)->getNumberOfNodes();
8123   (*it++)->setCoords(res);
8124   for(;it!=meshes.end();it++)
8125     {
8126       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8127       (*it)->setCoords(res);
8128       (*it)->shiftNodeNumbersInConn(offset);
8129       offset+=oldNumberOfNodes;
8130     }
8131 }
8132
8133 /*!
8134  * Merges nodes coincident with a given precision within all given meshes that share
8135  * the nodal connectivity array. The given meshes **can be of different** mesh
8136  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8137  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8138  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8139  *  \param [in,out] meshes - a vector of meshes to update.
8140  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8141  *  \throw If any of \a meshes is NULL.
8142  *  \throw If the \a meshes do not share the same node coordinates array.
8143  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8144  */
8145 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8146 {
8147   if(meshes.empty())
8148     return ;
8149   std::set<const DataArrayDouble *> s;
8150   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8151     {
8152       if(*it)
8153         s.insert((*it)->getCoords());
8154       else
8155         {
8156           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 !";
8157           throw INTERP_KERNEL::Exception(oss.str().c_str());
8158         }
8159     }
8160   if(s.size()!=1)
8161     {
8162       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 !";
8163       throw INTERP_KERNEL::Exception(oss.str().c_str());
8164     }
8165   const DataArrayDouble *coo=*(s.begin());
8166   if(!coo)
8167     return;
8168   //
8169   DataArrayInt *comm,*commI;
8170   coo->findCommonTuples(eps,-1,comm,commI);
8171   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8172   int oldNbOfNodes=coo->getNumberOfTuples();
8173   int newNbOfNodes;
8174   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8175   if(oldNbOfNodes==newNbOfNodes)
8176     return ;
8177   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8178   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8179     {
8180       (*it)->renumberNodesInConn(o2n->getConstPointer());
8181       (*it)->setCoords(newCoords);
8182     } 
8183 }
8184
8185 /*!
8186  * 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.
8187  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8188  * \param isQuad specifies the policy of connectivity.
8189  * @ret in/out parameter in which the result will be append
8190  */
8191 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8192 {
8193   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8194   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8195   ret.push_back(cm.getExtrudedType());
8196   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8197   switch(flatType)
8198   {
8199     case INTERP_KERNEL::NORM_POINT1:
8200       {
8201         ret.push_back(connBg[1]);
8202         ret.push_back(connBg[1]+nbOfNodesPerLev);
8203         break;
8204       }
8205     case INTERP_KERNEL::NORM_SEG2:
8206       {
8207         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8208         ret.insert(ret.end(),conn,conn+4);
8209         break;
8210       }
8211     case INTERP_KERNEL::NORM_SEG3:
8212       {
8213         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8214         ret.insert(ret.end(),conn,conn+8);
8215         break;
8216       }
8217     case INTERP_KERNEL::NORM_QUAD4:
8218       {
8219         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8220         ret.insert(ret.end(),conn,conn+8);
8221         break;
8222       }
8223     case INTERP_KERNEL::NORM_TRI3:
8224       {
8225         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8226         ret.insert(ret.end(),conn,conn+6);
8227         break;
8228       }
8229     case INTERP_KERNEL::NORM_TRI6:
8230       {
8231         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,
8232           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8233         ret.insert(ret.end(),conn,conn+15);
8234         break;
8235       }
8236     case INTERP_KERNEL::NORM_QUAD8:
8237       {
8238         int conn[20]={
8239           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8240           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8241           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8242         };
8243         ret.insert(ret.end(),conn,conn+20);
8244         break;
8245       }
8246     case INTERP_KERNEL::NORM_POLYGON:
8247       {
8248         std::back_insert_iterator< std::vector<int> > ii(ret);
8249         std::copy(connBg+1,connEnd,ii);
8250         *ii++=-1;
8251         std::reverse_iterator<const int *> rConnBg(connEnd);
8252         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8253         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8254         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8255         for(std::size_t i=0;i<nbOfRadFaces;i++)
8256           {
8257             *ii++=-1;
8258             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8259             std::copy(conn,conn+4,ii);
8260           }
8261         break;
8262       }
8263     default:
8264       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8265   }
8266 }
8267
8268 /*!
8269  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8270  */
8271 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8272 {
8273   std::size_t i, ip1;
8274   double v[3]={0.,0.,0.};
8275   std::size_t sz=std::distance(begin,end);
8276   if(isQuadratic)
8277     sz/=2;
8278   for(i=0;i<sz;i++)
8279     {
8280       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];
8281       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8282       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8283     }
8284   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8285
8286   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8287   // SEG3 forming a circle):
8288   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8289     {
8290       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8291       for(std::size_t j=0;j<sz;j++)
8292         {
8293           if (j%2)  // current point i is quadratic, next point i+1 is standard
8294             {
8295               i = sz+j;
8296               ip1 = (j+1)%sz; // ip1 = "i+1"
8297             }
8298           else      // current point i is standard, next point i+1 is quadratic
8299             {
8300               i = j;
8301               ip1 = j+sz;
8302             }
8303           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8304           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8305           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8306         }
8307       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8308     }
8309   return (ret>0.);
8310 }
8311
8312 /*!
8313  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8314  */
8315 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8316 {
8317   std::vector<std::pair<int,int> > edges;
8318   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8319   const int *bgFace=begin;
8320   for(std::size_t i=0;i<nbOfFaces;i++)
8321     {
8322       const int *endFace=std::find(bgFace+1,end,-1);
8323       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8324       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8325         {
8326           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8327           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8328             return false;
8329           edges.push_back(p1);
8330         }
8331       bgFace=endFace+1;
8332     }
8333   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8334 }
8335
8336 /*!
8337  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8338  */
8339 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8340 {
8341   double vec0[3],vec1[3];
8342   std::size_t sz=std::distance(begin,end);
8343   if(sz%2!=0)
8344     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8345   int nbOfNodes=(int)sz/2;
8346   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8347   const double *pt0=coords+3*begin[0];
8348   const double *pt1=coords+3*begin[nbOfNodes];
8349   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8350   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8351 }
8352
8353 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8354 {
8355   std::size_t sz=std::distance(begin,end);
8356   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8357   std::size_t nbOfNodes(sz/2);
8358   std::copy(begin,end,(int *)tmp);
8359   for(std::size_t j=1;j<nbOfNodes;j++)
8360     {
8361       begin[j]=tmp[nbOfNodes-j];
8362       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8363     }
8364 }
8365
8366 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8367 {
8368   std::size_t sz=std::distance(begin,end);
8369   if(sz!=4)
8370     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8371   double vec0[3],vec1[3];
8372   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8373   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]; 
8374   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;
8375 }
8376
8377 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8378 {
8379   std::size_t sz=std::distance(begin,end);
8380   if(sz!=5)
8381     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8382   double vec0[3];
8383   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8384   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8385   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8386 }
8387
8388 /*!
8389  * 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 ) 
8390  * 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
8391  * a 2D space.
8392  *
8393  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8394  * \param [in] coords the coordinates with nb of components exactly equal to 3
8395  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8396  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8397  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8398  */
8399 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8400 {
8401   int nbFaces=std::count(begin+1,end,-1)+1;
8402   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8403   double *vPtr=v->getPointer();
8404   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8405   double *pPtr=p->getPointer();
8406   const int *stFaceConn=begin+1;
8407   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8408     {
8409       const int *endFaceConn=std::find(stFaceConn,end,-1);
8410       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8411       stFaceConn=endFaceConn+1;
8412     }
8413   pPtr=p->getPointer(); vPtr=v->getPointer();
8414   DataArrayInt *comm1=0,*commI1=0;
8415   v->findCommonTuples(eps,-1,comm1,commI1);
8416   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8417   const int *comm1Ptr=comm1->getConstPointer();
8418   const int *commI1Ptr=commI1->getConstPointer();
8419   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8420   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8421   //
8422   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8423   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8424   mm->finishInsertingCells();
8425   //
8426   for(int i=0;i<nbOfGrps1;i++)
8427     {
8428       int vecId=comm1Ptr[commI1Ptr[i]];
8429       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8430       DataArrayInt *comm2=0,*commI2=0;
8431       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8432       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8433       const int *comm2Ptr=comm2->getConstPointer();
8434       const int *commI2Ptr=commI2->getConstPointer();
8435       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8436       for(int j=0;j<nbOfGrps2;j++)
8437         {
8438           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8439             {
8440               res->insertAtTheEnd(begin,end);
8441               res->pushBackSilent(-1);
8442             }
8443           else
8444             {
8445               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8446               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8447               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8448               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8449               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8450               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8451               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8452               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8453               const int *idsNodePtr=idsNode->getConstPointer();
8454               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];
8455               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8456               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8457               if(std::abs(norm)>eps)
8458                 {
8459                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8460                   mm3->rotate(center,vec,angle);
8461                 }
8462               mm3->changeSpaceDimension(2);
8463               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8464               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8465               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8466               int nbOfCells=mm4->getNumberOfCells();
8467               for(int k=0;k<nbOfCells;k++)
8468                 {
8469                   int l=0;
8470                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8471                     res->pushBackSilent(idsNodePtr[*work]);
8472                   res->pushBackSilent(-1);
8473                 }
8474             }
8475         }
8476     }
8477   res->popBackSilent();
8478 }
8479
8480 /*!
8481  * 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
8482  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8483  * 
8484  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8485  * \param [in] coords coordinates expected to have 3 components.
8486  * \param [in] begin start of the nodal connectivity of the face.
8487  * \param [in] end end of the nodal connectivity (excluded) of the face.
8488  * \param [out] v the normalized vector of size 3
8489  * \param [out] p the pos of plane
8490  */
8491 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8492 {
8493   std::size_t nbPoints=std::distance(begin,end);
8494   if(nbPoints<3)
8495     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8496   double vec[3]={0.,0.,0.};
8497   std::size_t j=0;
8498   bool refFound=false;
8499   for(;j<nbPoints-1 && !refFound;j++)
8500     {
8501       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8502       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8503       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8504       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8505       if(norm>eps)
8506         {
8507           refFound=true;
8508           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8509         }
8510     }
8511   for(std::size_t i=j;i<nbPoints-1;i++)
8512     {
8513       double curVec[3];
8514       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8515       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8516       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8517       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8518       if(norm<eps)
8519         continue;
8520       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8521       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];
8522       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8523       if(norm>eps)
8524         {
8525           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8526           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8527           return ;
8528         }
8529     }
8530   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8531 }
8532
8533 /*!
8534  * This method tries to obtain a well oriented polyhedron.
8535  * If the algorithm fails, an exception will be thrown.
8536  */
8537 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8538 {
8539   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8540   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8541   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8542   isPerm[0]=true;
8543   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8544   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8545   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8546   //
8547   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8548     {
8549       bgFace=begin;
8550       std::size_t smthChanged=0;
8551       for(std::size_t i=0;i<nbOfFaces;i++)
8552         {
8553           endFace=std::find(bgFace+1,end,-1);
8554           nbOfEdgesInFace=std::distance(bgFace,endFace);
8555           if(!isPerm[i])
8556             {
8557               bool b;
8558               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8559                 {
8560                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8561                   std::pair<int,int> p2(p1.second,p1.first);
8562                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8563                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8564                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8565                 }
8566               if(isPerm[i])
8567                 { 
8568                   if(!b)
8569                     std::reverse(bgFace+1,endFace);
8570                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8571                     {
8572                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8573                       std::pair<int,int> p2(p1.second,p1.first);
8574                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8575                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8576                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8577                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8578                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8579                       if(it!=edgesOK.end())
8580                         {
8581                           edgesOK.erase(it);
8582                           edgesFinished.push_back(p1);
8583                         }
8584                       else
8585                         edgesOK.push_back(p1);
8586                     }
8587                 }
8588             }
8589           bgFace=endFace+1;
8590         }
8591       if(smthChanged==0)
8592         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8593     }
8594   if(!edgesOK.empty())
8595     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8596   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8597     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8598       bgFace=begin;
8599       for(std::size_t i=0;i<nbOfFaces;i++)
8600         {
8601           endFace=std::find(bgFace+1,end,-1);
8602           std::reverse(bgFace+1,endFace);
8603           bgFace=endFace+1;
8604         }
8605     }
8606 }
8607
8608 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8609 {
8610   int nbOfNodesExpected(skin->getNumberOfNodes());
8611   const int *n2oPtr(n2o->getConstPointer());
8612   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8613   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8614   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8615   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8616   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8617   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8618   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8619   if(nbOfNodesExpected<1)
8620     return ret.retn();
8621   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8622   *work++=n2oPtr[prevNode];
8623   for(int i=1;i<nbOfNodesExpected;i++)
8624     {
8625       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8626         {
8627           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8628           conn.erase(prevNode);
8629           if(conn.size()==1)
8630             {
8631               int curNode(*(conn.begin()));
8632               *work++=n2oPtr[curNode];
8633               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8634               shar.erase(prevCell);
8635               if(shar.size()==1)
8636                 {
8637                   prevCell=*(shar.begin());
8638                   prevNode=curNode;
8639                 }
8640               else
8641                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8642             }
8643           else
8644             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8645         }
8646       else
8647         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8648     }
8649   return ret.retn();
8650 }
8651
8652 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8653 {
8654   int nbOfNodesExpected(skin->getNumberOfNodes());
8655   int nbOfTurn(nbOfNodesExpected/2);
8656   const int *n2oPtr(n2o->getConstPointer());
8657   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8658   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8659   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8660   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8661   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8662   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8663   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8664   if(nbOfNodesExpected<1)
8665     return ret.retn();
8666   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8667   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8668   for(int i=1;i<nbOfTurn;i++)
8669     {
8670       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8671         {
8672           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8673           conn.erase(prevNode);
8674           if(conn.size()==1)
8675             {
8676               int curNode(*(conn.begin()));
8677               *work=n2oPtr[curNode];
8678               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8679               shar.erase(prevCell);
8680               if(shar.size()==1)
8681                 {
8682                   int curCell(*(shar.begin()));
8683                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8684                   prevCell=curCell;
8685                   prevNode=curNode;
8686                   work++;
8687                 }
8688               else
8689                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8690             }
8691           else
8692             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8693         }
8694       else
8695         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8696     }
8697   return ret.retn();
8698 }
8699
8700 /*!
8701  * This method makes the assumption spacedimension == meshdimension == 2.
8702  * This method works only for linear cells.
8703  * 
8704  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8705  */
8706 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8707 {
8708   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8709     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8710   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8711   int oldNbOfNodes(skin->getNumberOfNodes());
8712   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8713   int nbOfNodesExpected(skin->getNumberOfNodes());
8714   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8715   int nbCells(skin->getNumberOfCells());
8716   if(nbCells==nbOfNodesExpected)
8717     return buildUnionOf2DMeshLinear(skin,n2o);
8718   else if(2*nbCells==nbOfNodesExpected)
8719     return buildUnionOf2DMeshQuadratic(skin,n2o);
8720   else
8721     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8722 }
8723
8724 /*!
8725  * This method makes the assumption spacedimension == meshdimension == 3.
8726  * This method works only for linear cells.
8727  * 
8728  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8729  */
8730 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8731 {
8732   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8733     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8734   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8735   const int *conn=m->getNodalConnectivity()->getConstPointer();
8736   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8737   int nbOfCells=m->getNumberOfCells();
8738   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8739   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8740   if(nbOfCells<1)
8741     return ret.retn();
8742   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8743   for(int i=1;i<nbOfCells;i++)
8744     {
8745       *work++=-1;
8746       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8747     }
8748   return ret.retn();
8749 }
8750
8751 /*!
8752  * \brief Creates a graph of cell neighbors
8753  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8754  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
8755  *  For example
8756  *  - index:  0 3 5 6 6
8757  *  - value:  1 2 3 2 3 3
8758  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8759  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8760  */
8761 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8762 {
8763   checkConnectivityFullyDefined();
8764
8765   int meshDim = this->getMeshDimension();
8766   ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8767   ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8768   this->getReverseNodalConnectivity(revConn,indexr);
8769   const int* indexr_ptr=indexr->getConstPointer();
8770   const int* revConn_ptr=revConn->getConstPointer();
8771
8772   const ParaMEDMEM::DataArrayInt* index;
8773   const ParaMEDMEM::DataArrayInt* conn;
8774   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8775   index=this->getNodalConnectivityIndex();
8776   int nbCells=this->getNumberOfCells();
8777   const int* index_ptr=index->getConstPointer();
8778   const int* conn_ptr=conn->getConstPointer();
8779
8780   //creating graph arcs (cell to cell relations)
8781   //arcs are stored in terms of (index,value) notation
8782   // 0 3 5 6 6
8783   // 1 2 3 2 3 3
8784   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8785   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8786
8787   //warning here one node have less than or equal effective number of cell with it
8788   //but cell could have more than effective nodes
8789   //because other equals nodes in other domain (with other global inode)
8790   std::vector <int> cell2cell_index(nbCells+1,0);
8791   std::vector <int> cell2cell;
8792   cell2cell.reserve(3*nbCells);
8793
8794   for (int icell=0; icell<nbCells;icell++)
8795     {
8796       std::map<int,int > counter;
8797       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8798         {
8799           int inode=conn_ptr[iconn];
8800           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8801             {
8802               int icell2=revConn_ptr[iconnr];
8803               std::map<int,int>::iterator iter=counter.find(icell2);
8804               if (iter!=counter.end()) (iter->second)++;
8805               else counter.insert(std::make_pair(icell2,1));
8806             }
8807         }
8808       for (std::map<int,int>::const_iterator iter=counter.begin();
8809            iter!=counter.end(); iter++)
8810         if (iter->second >= meshDim)
8811           {
8812             cell2cell_index[icell+1]++;
8813             cell2cell.push_back(iter->first);
8814           }
8815     }
8816   indexr->decrRef();
8817   revConn->decrRef();
8818   cell2cell_index[0]=0;
8819   for (int icell=0; icell<nbCells;icell++)
8820     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8821
8822   //filling up index and value to create skylinearray structure
8823   MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8824   return array;
8825 }
8826
8827 /*!
8828  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8829  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8830  */
8831 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8832 {
8833   double *w=zipFrmt;
8834   if(spaceDim==3)
8835     for(int i=0;i<nbOfNodesInCell;i++)
8836       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8837   else if(spaceDim==2)
8838     {
8839       for(int i=0;i<nbOfNodesInCell;i++)
8840         {
8841           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8842           *w++=0.;
8843         }
8844     }
8845   else
8846     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8847 }
8848
8849 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8850 {
8851   int nbOfCells=getNumberOfCells();
8852   if(nbOfCells<=0)
8853     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8854   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};
8855   ofs << "  <" << getVTKDataSetType() << ">\n";
8856   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8857   ofs << "      <PointData>\n" << pointData << std::endl;
8858   ofs << "      </PointData>\n";
8859   ofs << "      <CellData>\n" << cellData << std::endl;
8860   ofs << "      </CellData>\n";
8861   ofs << "      <Points>\n";
8862   if(getSpaceDimension()==3)
8863     _coords->writeVTK(ofs,8,"Points",byteData);
8864   else
8865     {
8866       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8867       coo->writeVTK(ofs,8,"Points",byteData);
8868     }
8869   ofs << "      </Points>\n";
8870   ofs << "      <Cells>\n";
8871   const int *cPtr=_nodal_connec->getConstPointer();
8872   const int *cIPtr=_nodal_connec_index->getConstPointer();
8873   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8874   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8875   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8876   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8877   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8878   int szFaceOffsets=0,szConn=0;
8879   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8880     {
8881       *w2=cPtr[cIPtr[i]];
8882       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8883         {
8884           *w1=-1;
8885           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8886           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8887         }
8888       else
8889         {
8890           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8891           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8892           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8893           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8894           w4=std::copy(c.begin(),c.end(),w4);
8895         }
8896     }
8897   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8898   types->writeVTK(ofs,8,"UInt8","types",byteData);
8899   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8900   if(szFaceOffsets!=0)
8901     {//presence of Polyhedra
8902       connectivity->reAlloc(szConn);
8903       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8904       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8905       w1=faces->getPointer();
8906       for(int i=0;i<nbOfCells;i++)
8907         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8908           {
8909             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8910             *w1++=nbFaces;
8911             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8912             for(int j=0;j<nbFaces;j++)
8913               {
8914                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8915                 *w1++=(int)std::distance(w6,w5);
8916                 w1=std::copy(w6,w5,w1);
8917                 w6=w5+1;
8918               }
8919           }
8920       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8921     }
8922   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8923   ofs << "      </Cells>\n";
8924   ofs << "    </Piece>\n";
8925   ofs << "  </" << getVTKDataSetType() << ">\n";
8926 }
8927
8928 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8929 {
8930   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8931   if(_mesh_dim==-2)
8932     { stream << " Not set !"; return ; }
8933   stream << " Mesh dimension : " << _mesh_dim << ".";
8934   if(_mesh_dim==-1)
8935     return ;
8936   if(!_coords)
8937     { stream << " No coordinates set !"; return ; }
8938   if(!_coords->isAllocated())
8939     { stream << " Coordinates set but not allocated !"; return ; }
8940   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8941   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8942   if(!_nodal_connec_index)
8943     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8944   if(!_nodal_connec_index->isAllocated())
8945     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8946   int lgth=_nodal_connec_index->getNumberOfTuples();
8947   int cpt=_nodal_connec_index->getNumberOfComponents();
8948   if(cpt!=1 || lgth<1)
8949     return ;
8950   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8951 }
8952
8953 std::string MEDCouplingUMesh::getVTKDataSetType() const
8954 {
8955   return std::string("UnstructuredGrid");
8956 }
8957
8958 std::string MEDCouplingUMesh::getVTKFileExtension() const
8959 {
8960   return std::string("vtu");
8961 }
8962
8963 /*!
8964  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8965  * returns a result mesh constituted by polygons.
8966  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8967  * all nodes from m2.
8968  * The meshes should be in 2D space. In
8969  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8970  * meshes.
8971  *  \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
8972  *                      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)
8973  *  \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
8974  *                      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)
8975  *  \param [in] eps - precision used to detect coincident mesh entities.
8976  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8977  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8978  *         this array using decrRef() as it is no more needed.
8979  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8980  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8981  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8982  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8983  *         it is no more needed.  
8984  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8985  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8986  *         is no more needed.  
8987  *  \throw If the coordinates array is not set in any of the meshes.
8988  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8989  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8990  *
8991  *  \sa conformize2D, mergeNodes
8992  */
8993 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8994                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8995 {
8996   if(!m1 || !m2)
8997     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8998   m1->checkFullyDefined();
8999   m2->checkFullyDefined();
9000   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9001     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
9002
9003   // Step 1: compute all edge intersections (new nodes)
9004   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9005   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9006   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9007   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9008   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9009                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9010                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9011   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9012   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9013   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9014
9015   // Step 2: re-order newly created nodes according to the ordering found in m2
9016   std::vector< std::vector<int> > intersectEdge2;
9017   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9018   subDiv2.clear(); dd5=0; dd6=0;
9019
9020   // Step 3:
9021   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9022   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9023   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9024                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9025
9026   // Step 4: Prepare final result:
9027   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9028   addCooDa->alloc((int)(addCoo.size())/2,2);
9029   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9030   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9031   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9032   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9033   std::vector<const DataArrayDouble *> coordss(4);
9034   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9035   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9036   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9037   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9038   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9039   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9040   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9041   ret->setConnectivity(conn,connI,true);
9042   ret->setCoords(coo);
9043   cellNb1=c1.retn(); cellNb2=c2.retn();
9044   return ret.retn();
9045 }
9046
9047 /// @cond INTERNAL
9048
9049 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9050 {
9051   if(candidates.empty())
9052     return false;
9053   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9054     {
9055       const std::vector<int>& pool(intersectEdge1[*it]);
9056       int tmp[2]; tmp[0]=start; tmp[1]=stop;
9057       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9058         {
9059           retVal=*it+1;
9060           return true;
9061         }
9062       tmp[0]=stop; tmp[1]=start;
9063       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9064         {
9065           retVal=-*it-1;
9066           return true;
9067         }
9068     }
9069   return false;
9070 }
9071
9072 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,
9073                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9074 {
9075   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9076   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9077   int nCells(mesh1D->getNumberOfCells());
9078   if(nCells!=(int)intersectEdge2.size())
9079     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9080   const DataArrayDouble *coo2(mesh1D->getCoords());
9081   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9082   const double *coo2Ptr(coo2->begin());
9083   int offset1(coords1->getNumberOfTuples());
9084   int offset2(offset1+coo2->getNumberOfTuples());
9085   int offset3(offset2+addCoo.size()/2);
9086   std::vector<double> addCooQuad;
9087   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9088   int tmp[4],cicnt(0),kk(0);
9089   for(int i=0;i<nCells;i++)
9090     {
9091       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9092       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9093       const std::vector<int>& subEdges(intersectEdge2[i]);
9094       int nbSubEdge(subEdges.size()/2);
9095       for(int j=0;j<nbSubEdge;j++,kk++)
9096         {
9097           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));
9098           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9099           INTERP_KERNEL::Edge *e2Ptr(e2);
9100           std::map<int,int>::const_iterator itm;
9101           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9102             {
9103               tmp[0]=INTERP_KERNEL::NORM_SEG3;
9104               itm=mergedNodes.find(subEdges[2*j]);
9105               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9106               itm=mergedNodes.find(subEdges[2*j+1]);
9107               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9108               tmp[3]=offset3+(int)addCooQuad.size()/2;
9109               double tmp2[2];
9110               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9111               cicnt+=4;
9112               cOut->insertAtTheEnd(tmp,tmp+4);
9113               ciOut->pushBackSilent(cicnt);
9114             }
9115           else
9116             {
9117               tmp[0]=INTERP_KERNEL::NORM_SEG2;
9118               itm=mergedNodes.find(subEdges[2*j]);
9119               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9120               itm=mergedNodes.find(subEdges[2*j+1]);
9121               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9122               cicnt+=3;
9123               cOut->insertAtTheEnd(tmp,tmp+3);
9124               ciOut->pushBackSilent(cicnt);
9125             }
9126           int tmp00;
9127           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9128             {
9129               idsInRetColinear->pushBackSilent(kk);
9130               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9131             }
9132         }
9133       e->decrRef();
9134     }
9135   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9136   ret->setConnectivity(cOut,ciOut,true);
9137   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9138   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9139   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9140   std::vector<const DataArrayDouble *> coordss(4);
9141   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9142   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9143   ret->setCoords(arr);
9144   return ret.retn();
9145 }
9146
9147 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9148 {
9149   std::vector<int> allEdges;
9150   for(const int *it2(descBg);it2!=descEnd;it2++)
9151     {
9152       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9153       if(*it2>0)
9154         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9155       else
9156         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9157     }
9158   std::size_t nb(allEdges.size());
9159   if(nb%2!=0)
9160     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9161   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9162   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9163   ret->setCoords(coords);
9164   ret->allocateCells(1);
9165   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9166   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9167     connOut[kk]=allEdges[2*kk];
9168   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9169   return ret.retn();
9170 }
9171
9172 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9173 {
9174   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9175   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9176   std::size_t ii(0);
9177   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9178   if(sz!=std::distance(descBg,descEnd))
9179     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9180   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9181   std::vector<int> allEdges,centers;
9182   const double *coordsPtr(coords->begin());
9183   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9184   int offset(coords->getNumberOfTuples());
9185   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9186     {
9187       INTERP_KERNEL::NormalizedCellType typeOfSon;
9188       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9189       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9190       if(*it2>0)
9191         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9192       else
9193         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9194       if(edge1.size()==2)
9195         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9196       else
9197         {//the current edge has been subsplit -> create corresponding centers.
9198           std::size_t nbOfCentersToAppend(edge1.size()/2);
9199           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9200           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9201           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9202           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9203             {
9204               double tmpp[2];
9205               const double *aa(coordsPtr+2*(*it3++));
9206               const double *bb(coordsPtr+2*(*it3++));
9207               ee->getMiddleOfPoints(aa,bb,tmpp);
9208               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9209               centers.push_back(offset+k);
9210             }
9211         }
9212     }
9213   std::size_t nb(allEdges.size());
9214   if(nb%2!=0)
9215     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9216   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9217   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9218   if(addCoo->empty())
9219     ret->setCoords(coords);
9220   else
9221     {
9222       addCoo->rearrange(2);
9223       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9224       ret->setCoords(addCoo);
9225     }
9226   ret->allocateCells(1);
9227   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9228   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9229     connOut[kk]=allEdges[2*kk];
9230   connOut.insert(connOut.end(),centers.begin(),centers.end());
9231   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9232   return ret.retn();
9233 }
9234
9235 /*!
9236  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9237  * of those edges.
9238  *
9239  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9240  */
9241 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9242 {
9243   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9244   if(!cm.isQuadratic())
9245     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9246   else
9247     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9248 }
9249
9250 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9251 {
9252   bool isQuad(false);
9253   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9254     {
9255       const INTERP_KERNEL::Edge *ee(*it);
9256       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9257         isQuad=true;
9258     }
9259   if(!isQuad)
9260     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9261   else
9262     {
9263       const double *coo(mesh2D->getCoords()->begin());
9264       std::size_t sz(conn.size());
9265       std::vector<double> addCoo;
9266       std::vector<int> conn2(conn);
9267       int offset(mesh2D->getNumberOfNodes());
9268       for(std::size_t i=0;i<sz;i++)
9269         {
9270           double tmp[2];
9271           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9272           addCoo.insert(addCoo.end(),tmp,tmp+2);
9273           conn2.push_back(offset+(int)i);
9274         }
9275       mesh2D->getCoords()->rearrange(1);
9276       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9277       mesh2D->getCoords()->rearrange(2);
9278       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9279     }
9280 }
9281
9282 /*!
9283  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9284  *
9285  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9286  * a set of edges defined in \a splitMesh1D.
9287  */
9288 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9289                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9290 {
9291   std::size_t nb(edge1Bis.size()/2);
9292   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9293   int iEnd(splitMesh1D->getNumberOfCells());
9294   if(iEnd==0)
9295     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9296   std::size_t ii,jj;
9297   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9298   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9299   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9300   //
9301   if(jj==nb)
9302     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9303       out0.resize(1); out1.resize(1);
9304       std::vector<int>& connOut(out0[0]);
9305       connOut.resize(nbOfEdgesOf2DCellSplit);
9306       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9307       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9308       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9309         {
9310           connOut[kk]=edge1Bis[2*kk];
9311           edgesPtr[kk]=edge1BisPtr[2*kk];
9312         }
9313     }
9314   else
9315     {
9316       // [i,iEnd[ contains the
9317       out0.resize(2); out1.resize(2);
9318       std::vector<int>& connOutLeft(out0[0]);
9319       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9320       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9321       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9322       for(std::size_t k=ii;k<jj+1;k++)
9323         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9324       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9325       for(int ik=0;ik<iEnd;ik++)
9326         {
9327           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9328           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9329           ees[ik]=ee;
9330         }
9331       for(int ik=iEnd-1;ik>=0;ik--)
9332         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9333       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9334         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9335       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9336       for(int ik=0;ik<iEnd;ik++)
9337         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9338       eright.insert(eright.end(),ees.begin(),ees.end());
9339     }
9340 }
9341
9342 /// @endcond
9343
9344 /// @cond INTERNAL
9345
9346 struct CellInfo
9347 {
9348 public:
9349   CellInfo() { }
9350   CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9351 public:
9352   std::vector<int> _edges;
9353   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9354 };
9355
9356 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9357 {
9358   std::size_t nbe(edges.size());
9359   std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9360   for(std::size_t i=0;i<nbe;i++)
9361     {
9362       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9363       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9364     }
9365   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9366   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9367   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9368 }
9369
9370 class EdgeInfo
9371 {
9372 public:
9373   EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9374   EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9375   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9376   void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9377   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9378 private:
9379   int _istart;
9380   int _iend;
9381   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9382   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9383   int _left;
9384   int _right;
9385 };
9386
9387 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9388 {
9389   const MEDCouplingUMesh *mesh(_mesh);
9390   if(mesh)
9391     return ;
9392   if(_right<pos)
9393     return ;
9394   if(_left>pos)
9395     { _left++; _right++; return ; }
9396   if(_right==pos)
9397     {
9398       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9399       if((isLeft && isRight) || (!isLeft && !isRight))
9400         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9401       if(isLeft)
9402         return ;
9403       if(isRight)
9404         {
9405           _right++;
9406           return ;
9407         }
9408     }
9409   if(_left==pos)
9410     {
9411       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9412       if((isLeft && isRight) || (!isLeft && !isRight))
9413         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9414       if(isLeft)
9415         {
9416           _right++;
9417           return ;
9418         }
9419       if(isRight)
9420         {
9421           _left++;
9422           _right++;
9423           return ;
9424         }
9425     }
9426 }
9427
9428 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9429 {
9430   const MEDCouplingUMesh *mesh(_mesh);
9431   if(!mesh)
9432     {
9433       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9434     }
9435   else
9436     {// not fully splitting cell case
9437       if(mesh2D->getNumberOfCells()==1)
9438         {//little optimization. 1 cell no need to find in which cell mesh is !
9439           neighbors[0]=offset; neighbors[1]=offset;
9440           return;
9441         }
9442       else
9443         {
9444           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9445           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9446           if(cellId==-1)
9447             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9448           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9449         }
9450     }
9451 }
9452
9453 class VectorOfCellInfo
9454 {
9455 public:
9456   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9457   std::size_t size() const { return _pool.size(); }
9458   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9459   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);
9460   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9461   const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9462   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9463   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9464 private:
9465   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9466   void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9467   const CellInfo& get(int pos) const;
9468   CellInfo& get(int pos);
9469 private:
9470   std::vector<CellInfo> _pool;
9471   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9472   std::vector<EdgeInfo> _edge_info;
9473 };
9474
9475 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9476 {
9477   _pool[0]._edges=edges;
9478   _pool[0]._edges_ptr=edgesPtr;
9479 }
9480
9481 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9482 {
9483   if(_pool.empty())
9484     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9485   if(_pool.size()==1)
9486     return 0;
9487   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9488   if(!zeMesh)
9489     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9490   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9491   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9492 }
9493
9494 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)
9495 {
9496   get(pos);//to check pos
9497   bool isFast(pos==0 && _pool.size()==1);
9498   std::size_t sz(edges.size());
9499   // dealing with edges
9500   if(sz==1)
9501     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9502   else
9503     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9504   //
9505   std::vector<CellInfo> pool(_pool.size()-1+sz);
9506   for(int i=0;i<pos;i++)
9507     pool[i]=_pool[i];
9508   for(std::size_t j=0;j<sz;j++)
9509     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9510   for(int i=pos+1;i<(int)_pool.size();i++)
9511     pool[i+sz-1]=_pool[i];
9512   _pool=pool;
9513   //
9514   if(sz==2)
9515     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9516   //
9517   if(isFast)
9518     {
9519       _ze_mesh=mesh;
9520       return ;
9521     }
9522   //
9523   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9524   if(pos>0)
9525     {
9526       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9527       ms.push_back(elt);
9528     }
9529   ms.push_back(mesh);
9530   if(pos<_ze_mesh->getNumberOfCells()-1)
9531   {
9532     MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9533     ms.push_back(elt);
9534   }
9535   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9536   for(std::size_t j=0;j<ms2.size();j++)
9537     ms2[j]=ms[j];
9538   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9539 }
9540
9541 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9542 {
9543   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9544 }
9545
9546 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9547 {
9548   if(pos<0)
9549     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9550   int ret(0);
9551   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9552     {
9553       if((*it).isInMyRange(pos))
9554         return ret;
9555     }
9556   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9557 }
9558
9559 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9560 {
9561   get(pos);//to check;
9562   if(_edge_info.empty())
9563     return ;
9564   std::size_t sz(_edge_info.size()-1);
9565   for(std::size_t i=0;i<sz;i++)
9566     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9567 }
9568
9569 const CellInfo& VectorOfCellInfo::get(int pos) const
9570 {
9571   if(pos<0 || pos>=(int)_pool.size())
9572     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9573   return _pool[pos];
9574 }
9575
9576 CellInfo& VectorOfCellInfo::get(int pos)
9577 {
9578   if(pos<0 || pos>=(int)_pool.size())
9579     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9580   return _pool[pos];
9581 }
9582
9583 /*!
9584  * Given :
9585  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9586  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9587  *
9588  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9589  *
9590  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9591  *
9592  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9593  */
9594 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9595                                          MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9596 {
9597   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9598   if(nbCellsInSplitMesh1D==0)
9599     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9600   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9601   std::size_t nb(allEdges.size()),jj;
9602   if(nb%2!=0)
9603     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9604   std::vector<int> edge1Bis(nb*2);
9605   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9606   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9607   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9608   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9609   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9610   //
9611   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9612   int *idsLeftRightPtr(idsLeftRight->getPointer());
9613   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9614   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9615     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9616       int iEnd(iStart);
9617       for(;iEnd<nbCellsInSplitMesh1D;)
9618         {
9619           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9620           if(jj!=nb)
9621             break;
9622           else
9623             iEnd++;
9624         }
9625       if(iEnd<nbCellsInSplitMesh1D)
9626         iEnd++;
9627       //
9628       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9629       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9630       //
9631       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9632       retTmp->setCoords(splitMesh1D->getCoords());
9633       retTmp->allocateCells();
9634
9635       std::vector< std::vector<int> > out0;
9636       std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9637
9638       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9639       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9640         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9641       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9642       //
9643       iStart=iEnd;
9644     }
9645   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9646     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9647   return pool.getZeMesh().retn();
9648 }
9649
9650 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9651                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9652                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9653 {
9654   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9655   //
9656   std::vector<int> allEdges;
9657   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9658   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9659     {
9660       int edgeId(std::abs(*it)-1);
9661       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9662       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9663       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9664       if(*it>0)
9665         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9666       else
9667         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9668       std::size_t sz(edge1.size());
9669       for(std::size_t cnt=0;cnt<sz;cnt++)
9670         allEdgesPtr.push_back(ee);
9671     }
9672   //
9673   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9674 }
9675
9676 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9677 {
9678   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9679     {//easy case comparison not
9680       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9681     }
9682   else if(typ1.isQuadratic() && typ2.isQuadratic())
9683     {
9684       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9685       if(!status0)
9686         return false;
9687       if(conn1[2]==conn2[2])
9688         return true;
9689       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9690       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9691       return dist<eps;
9692     }
9693   else
9694     {//only one is quadratic
9695       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9696       if(!status0)
9697         return false;
9698       const double *a(0),*bb(0),*be(0);
9699       if(typ1.isQuadratic())
9700         {
9701           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9702         }
9703       else
9704         {
9705           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9706         }
9707       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9708       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9709       return dist<eps;
9710     }
9711 }
9712
9713 /*!
9714  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9715  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9716  *
9717  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9718  */
9719 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9720 {
9721   if(candidatesIn2DEnd==candidatesIn2DBg)
9722     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9723   const double *coo(mesh2DSplit->getCoords()->begin());
9724   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9725     return *candidatesIn2DBg;
9726   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9727   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9728   if(cellIdInMesh1DSplitRelative<0)
9729     cur1D->changeOrientationOfCells();
9730   const int *c1D(cur1D->getNodalConnectivity()->begin());
9731   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9732   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9733     {
9734       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9735       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9736       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9737       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9738       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9739       for(unsigned it2=0;it2<sz;it2++)
9740         {
9741           INTERP_KERNEL::NormalizedCellType typeOfSon;
9742           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9743           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9744           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9745             return *it;
9746         }
9747     }
9748   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9749 }
9750
9751 /// @endcond
9752
9753 /*!
9754  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9755  * 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
9756  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9757  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9758  *
9759  * \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
9760  *                      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)
9761  * \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
9762  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9763  * \param [in] eps - precision used to perform intersections and localization operations.
9764  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9765  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9766  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9767  *                               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.
9768  * \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
9769  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9770  *                               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.
9771  *
9772  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9773  */
9774 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9775 {
9776   if(!mesh2D || !mesh1D)
9777     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9778   mesh2D->checkFullyDefined();
9779   mesh1D->checkFullyDefined();
9780   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9781   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9782     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9783   // Step 1: compute all edge intersections (new nodes)
9784   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9785   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9786   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9787   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9788   //
9789   // Build desc connectivity
9790   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9791   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9792   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9793   std::map<int,int> mergedNodes;
9794   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9795   // use mergeNodes to fix intersectEdge1
9796   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9797     {
9798       std::size_t n((*it0).size()/2);
9799       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9800       std::map<int,int>::const_iterator it1;
9801       it1=mergedNodes.find(eltStart);
9802       if(it1!=mergedNodes.end())
9803         (*it0)[0]=(*it1).second;
9804       it1=mergedNodes.find(eltEnd);
9805       if(it1!=mergedNodes.end())
9806         (*it0)[2*n-1]=(*it1).second;
9807     }
9808   //
9809   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9810   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9811   // Step 2: re-order newly created nodes according to the ordering found in m2
9812   std::vector< std::vector<int> > intersectEdge2;
9813   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9814   subDiv2.clear();
9815   // Step 3: compute splitMesh1D
9816   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9817   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9818   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9819       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9822   // deal with cells in mesh2D that are not cut but only some of their edges are
9823   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9824   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9825   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9826   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
9827   if(!idsInDesc2DToBeRefined->empty())
9828     {
9829       DataArrayInt *out0(0),*outi0(0);
9830       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9831       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9832       out0s=out0;
9833       out0s=out0s->buildUnique();
9834       out0s->sort(true);
9835     }
9836   //
9837   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9838   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9839   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9840   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9841   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9842   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9843   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9844     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9845   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9846   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9847   if((DataArrayInt *)out0s)
9848     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9849   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9850   // OK all is ready to insert in ret2 mesh
9851   if(!untouchedCells->empty())
9852     {// the most easy part, cells in mesh2D not impacted at all
9853       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9854       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9855       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9856     }
9857   if((DataArrayInt *)out0s)
9858     {// here dealing with cells in out0s but not in cellsToBeModified
9859       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9860       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9861       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9862         {
9863           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9864           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9865         }
9866       int offset(ret2->getNumberOfTuples());
9867       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9868       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9869       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9870       int kk(0),*ret3ptr(partOfRet3->getPointer());
9871       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9872         {
9873           int faceId(std::abs(*it)-1);
9874           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9875             {
9876               int tmp(fewModifiedCells->locateValue(*it2));
9877               if(tmp!=-1)
9878                 {
9879                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9880                     ret3ptr[2*kk]=tmp+offset;
9881                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9882                     ret3ptr[2*kk+1]=tmp+offset;
9883                 }
9884               else
9885                 {//the current edge is shared by a 2D cell that will be split just after
9886                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9887                     ret3ptr[2*kk]=-(*it2+1);
9888                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9889                     ret3ptr[2*kk+1]=-(*it2+1);
9890                 }
9891             }
9892         }
9893       m1Desc->setCoords(ret1->getCoords());
9894       ret1NonCol->setCoords(ret1->getCoords());
9895       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9896       if(!outMesh2DSplit.empty())
9897         {
9898           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9899           for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9900             (*itt)->setCoords(da);
9901         }
9902     }
9903   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9904   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9905     {
9906       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9907       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9908       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9909       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9910       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9911       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));
9912       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9913       outMesh2DSplit.push_back(splitOfOneCell);
9914       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9915         ret2->pushBackSilent(*it);
9916     }
9917   //
9918   std::size_t nbOfMeshes(outMesh2DSplit.size());
9919   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9920   for(std::size_t i=0;i<nbOfMeshes;i++)
9921     tmp[i]=outMesh2DSplit[i];
9922   //
9923   ret1->getCoords()->setInfoOnComponents(compNames);
9924   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9925   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9926   ret3->rearrange(1);
9927   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9928   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9929     {
9930       int old2DCellId(-ret3->getIJ(*it,0)-1);
9931       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9932       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
9933     }
9934   ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9935   ret3->rearrange(2);
9936   //
9937   splitMesh1D=ret1.retn();
9938   splitMesh2D=ret2D.retn();
9939   cellIdInMesh2D=ret2.retn();
9940   cellIdInMesh1D=ret3.retn();
9941 }
9942
9943 /**
9944  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9945  * (newly created) nodes corresponding to the edge intersections.
9946  * Output params:
9947  * @param[out] cr, crI connectivity of the resulting mesh
9948  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9949  * TODO: describe input parameters
9950  */
9951 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9952                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9953                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9954                                                          const std::vector<double>& addCoords,
9955                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9956 {
9957   static const int SPACEDIM=2;
9958   const double *coo1(m1->getCoords()->getConstPointer());
9959   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9960   int offset1(m1->getNumberOfNodes());
9961   const double *coo2(m2->getCoords()->getConstPointer());
9962   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9963   int offset2(offset1+m2->getNumberOfNodes());
9964   int offset3(offset2+((int)addCoords.size())/2);
9965   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9966   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9967   // Here a BBTree on 2D-cells, not on segments:
9968   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9969   int ncell1(m1->getNumberOfCells());
9970   crI.push_back(0);
9971   for(int i=0;i<ncell1;i++)
9972     {
9973       std::vector<int> candidates2;
9974       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9975       std::map<INTERP_KERNEL::Node *,int> mapp;
9976       std::map<int,INTERP_KERNEL::Node *> mappRev;
9977       INTERP_KERNEL::QuadraticPolygon pol1;
9978       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9979       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9980       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9981       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9982       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9983       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9984           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9985       //
9986       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
9987       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9988       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9989       for(it1.first();!it1.finished();it1.next())
9990         edges1.insert(it1.current()->getPtr());
9991       //
9992       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9993       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9994       int ii=0;
9995       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9996         {
9997           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9998           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9999           // Complete mapping with elements coming from the current cell it2 in mesh2:
10000           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10001           // pol2 is the new QP in the final merged result.
10002           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10003               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10004         }
10005       ii=0;
10006       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10007         {
10008           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10009           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10010           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10011           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10012         }
10013       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10014       // by m2 but that we still want to keep in the final result.
10015       if(!edges1.empty())
10016         {
10017           try
10018           {
10019               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10020           }
10021           catch(INTERP_KERNEL::Exception& e)
10022           {
10023               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();
10024               throw INTERP_KERNEL::Exception(oss.str().c_str());
10025           }
10026         }
10027       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10028         (*it).second->decrRef();
10029     }
10030 }
10031
10032 /**
10033  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10034  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10035  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10036  * The caller is to deal with the resulting DataArrayInt.
10037  *  \throw If the coordinate array is not set.
10038  *  \throw If the nodal connectivity of the cells is not defined.
10039  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10040  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10041  *
10042  * \sa DataArrayInt::sortEachPairToMakeALinkedList
10043  */
10044 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10045 {
10046   checkFullyDefined();
10047   if(getMeshDimension()!=1)
10048     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10049
10050   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10051   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10052   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10053   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10054   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10055   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10056   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10057   const int * dsi(_dsi->getConstPointer());
10058   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
10059   m_points=0;
10060   if (dsii->getNumberOfTuples())
10061     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10062
10063   int nc(getNumberOfCells());
10064   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10065   result->alloc(nc,1);
10066
10067   // set of edges not used so far
10068   std::set<int> edgeSet;
10069   for (int i=0; i<nc; edgeSet.insert(i), i++);
10070
10071   int startSeg=0;
10072   int newIdx=0;
10073   // while we have points with only one neighbor segments
10074   do
10075     {
10076       std::list<int> linePiece;
10077       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10078       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10079         {
10080           // Fill the list forward (resp. backward) from the start segment:
10081           int activeSeg = startSeg;
10082           int prevPointId = -20;
10083           int ptId;
10084           while (!edgeSet.empty())
10085             {
10086               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10087                 {
10088                   if (direction==0)
10089                     linePiece.push_back(activeSeg);
10090                   else
10091                     linePiece.push_front(activeSeg);
10092                   edgeSet.erase(activeSeg);
10093                 }
10094
10095               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10096               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10097               if (dsi[ptId] == 1) // hitting the end of the line
10098                 break;
10099               prevPointId = ptId;
10100               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10101               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10102             }
10103         }
10104       // Done, save final piece into DA:
10105       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10106       newIdx += linePiece.size();
10107
10108       // identify next valid start segment (one which is not consumed)
10109       if(!edgeSet.empty())
10110         startSeg = *(edgeSet.begin());
10111     }
10112   while (!edgeSet.empty());
10113   return result.retn();
10114 }
10115
10116 /// @cond INTERNAL
10117
10118 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10119 {
10120   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10121   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10122   if(it==m.end())
10123     throw INTERP_KERNEL::Exception("Internal error in remapping !");
10124   int v((*it).second);
10125   if(v==forbVal0 || v==forbVal1)
10126     return ;
10127   if(std::find(isect.begin(),isect.end(),v)==isect.end())
10128     isect.push_back(v);
10129 }
10130
10131 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10132 {
10133   int sz(c.size());
10134   if(sz<=1)
10135     return false;
10136   bool presenceOfOn(false);
10137   for(int i=0;i<sz;i++)
10138     {
10139       INTERP_KERNEL::ElementaryEdge *e(c[i]);
10140       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10141         continue ;
10142       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10143       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10144     }
10145   return presenceOfOn;
10146 }
10147
10148 /// @endcond
10149
10150 /**
10151  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10152  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10153  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10154  * a minimal creation of new nodes is wanted.
10155  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10156  * nodes if a SEG3 is split without information of middle.
10157  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10158  * avoid to have a non conform mesh.
10159  *
10160  * \return int - the number of new nodes created (in most of cases 0).
10161  * 
10162  * \throw If \a this is not coherent.
10163  * \throw If \a this has not spaceDim equal to 2.
10164  * \throw If \a this has not meshDim equal to 2.
10165  * \throw If some subcells needed to be split are orphan.
10166  * \sa MEDCouplingUMesh::conformize2D
10167  */
10168 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10169 {
10170   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10171     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10172   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10173   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10174     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10175   if(midOpt==0 && midOptI==0)
10176     {
10177       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10178       return 0;
10179     }
10180   else if(midOpt!=0 && midOptI!=0)
10181     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10182   else
10183     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10184 }
10185
10186 /*!
10187  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10188  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10189  * 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
10190  * 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).
10191  * 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.
10192  * 
10193  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10194  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10195  *
10196  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10197  * This method expects that all nodes in \a this are not closer than \a eps.
10198  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10199  * 
10200  * \param [in] eps the relative error to detect merged edges.
10201  * \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
10202  *                           that the user is expected to deal with.
10203  *
10204  * \throw If \a this is not coherent.
10205  * \throw If \a this has not spaceDim equal to 2.
10206  * \throw If \a this has not meshDim equal to 2.
10207  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10208  */
10209 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10210 {
10211   static const int SPACEDIM=2;
10212   checkCoherency();
10213   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10214     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10215   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10216   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10217   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10218   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10219   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10220   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10221   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10222   std::vector<double> addCoo;
10223   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10224   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10225   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10226   for(int i=0;i<nDescCell;i++)
10227     {
10228       std::vector<int> candidates;
10229       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10230       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10231         if(*it>i)
10232           {
10233             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10234             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10235                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10236             INTERP_KERNEL::MergePoints merge;
10237             INTERP_KERNEL::QuadraticPolygon c1,c2;
10238             e1->intersectWith(e2,merge,c1,c2);
10239             e1->decrRef(); e2->decrRef();
10240             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10241               overlapEdge[i].push_back(*it);
10242             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10243               overlapEdge[*it].push_back(i);
10244           }
10245     }
10246   // splitting done. sort intersect point in intersectEdge.
10247   std::vector< std::vector<int> > middle(nDescCell);
10248   int nbOf2DCellsToBeSplit(0);
10249   bool middleNeedsToBeUsed(false);
10250   std::vector<bool> cells2DToTreat(nDescCell,false);
10251   for(int i=0;i<nDescCell;i++)
10252     {
10253       std::vector<int>& isect(intersectEdge[i]);
10254       int sz((int)isect.size());
10255       if(sz>1)
10256         {
10257           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10258           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10259           e->sortSubNodesAbs(coords,isect);
10260           e->decrRef();
10261         }
10262       if(sz!=0)
10263         {
10264           int idx0(rdi[i]),idx1(rdi[i+1]);
10265           if(idx1-idx0!=1)
10266             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10267           if(!cells2DToTreat[rd[idx0]])
10268             {
10269               cells2DToTreat[rd[idx0]]=true;
10270               nbOf2DCellsToBeSplit++;
10271             }
10272           // try to reuse at most eventual 'middle' of SEG3
10273           std::vector<int>& mid(middle[i]);
10274           mid.resize(sz+1,-1);
10275           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10276             {
10277               middleNeedsToBeUsed=true;
10278               const std::vector<int>& candidates(overlapEdge[i]);
10279               std::vector<int> trueCandidates;
10280               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10281                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10282                   trueCandidates.push_back(*itc);
10283               int stNode(c[ci[i]+1]),endNode(isect[0]);
10284               for(int j=0;j<sz+1;j++)
10285                 {
10286                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10287                     {
10288                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10289                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10290                         { mid[j]=*itc; break; }
10291                     }
10292                   stNode=endNode;
10293                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10294                 }
10295             }
10296         }
10297     }
10298   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10299   if(nbOf2DCellsToBeSplit==0)
10300     return ret.retn();
10301   //
10302   int *retPtr(ret->getPointer());
10303   for(int i=0;i<nCell;i++)
10304     if(cells2DToTreat[i])
10305       *retPtr++=i;
10306   //
10307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10308   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10309   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10310   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10311   if(middleNeedsToBeUsed)
10312     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10313   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10314   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10315   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.
10316   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10317   {
10318     bool areNodesMerged; int newNbOfNodes;
10319     if(nbOfNodesCreated!=0)
10320       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10321   }
10322   return ret.retn();
10323 }
10324
10325 /*!
10326  * 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.
10327  * 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).
10328  * 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
10329  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10330  * 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
10331  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10332  *
10333  * 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
10334  * using new instance, idem for coordinates.
10335  *
10336  * 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.
10337  * 
10338  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10339  *
10340  * \throw If \a this is not coherent.
10341  * \throw If \a this has not spaceDim equal to 2.
10342  * \throw If \a this has not meshDim equal to 2.
10343  * 
10344  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10345  */
10346 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10347 {
10348   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10349   checkCoherency();
10350   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10351     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10352   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10353   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10354   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10355   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10356   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10357   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10358   const double *coords(_coords->begin());
10359   int *newciptr(newci->getPointer());
10360   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10361     {
10362       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10363         ret->pushBackSilent(i);
10364       newciptr[1]=newc->getNumberOfTuples();
10365     }
10366   //
10367   if(ret->empty())
10368     return ret.retn();
10369   if(!appendedCoords->empty())
10370     {
10371       appendedCoords->rearrange(2);
10372       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10373       //non const part
10374       setCoords(newCoords);
10375     }
10376   //non const part
10377   setConnectivity(newc,newci,true);
10378   return ret.retn();
10379 }
10380
10381 /*!
10382  * \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.
10383  *                               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.
10384  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10385  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10386  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10387  * \param [out] addCoo - nodes to be append at the end
10388  * \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.
10389  */
10390 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10391                                          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)
10392 {
10393   static const int SPACEDIM=2;
10394   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10395   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10396   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10397   // Build BB tree of all edges in the tool mesh (second mesh)
10398   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10399   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10400   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10401   intersectEdge1.resize(nDescCell1);
10402   colinear2.resize(nDescCell2);
10403   subDiv2.resize(nDescCell2);
10404   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10405
10406   std::vector<int> candidates1(1);
10407   int offset1(m1Desc->getNumberOfNodes());
10408   int offset2(offset1+m2Desc->getNumberOfNodes());
10409   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10410     {
10411       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10412       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10413       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10414         {
10415           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10416           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10417           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10418           candidates1[0]=i;
10419           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10420           // 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
10421           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10422           std::set<INTERP_KERNEL::Node *> nodes;
10423           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10424           std::size_t szz(nodes.size());
10425           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10426           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10427           for(std::size_t iii=0;iii<szz;iii++,itt++)
10428             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10429           // end of protection
10430           // Performs egde cutting:
10431           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10432           delete pol2;
10433           delete pol1;
10434         }
10435       else
10436         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10437         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10438     }
10439 }
10440
10441 /*!
10442  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10443  * It builds the descending connectivity of the two meshes, and then using a binary tree
10444  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10445  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10446  */
10447 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10448                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10449                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10450                                                    std::vector<double>& addCoo,
10451                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10452 {
10453   // Build desc connectivity
10454   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10455   desc2=DataArrayInt::New();
10456   descIndx2=DataArrayInt::New();
10457   revDesc2=DataArrayInt::New();
10458   revDescIndx2=DataArrayInt::New();
10459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10461   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10462   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10463   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10464   std::map<int,int> notUsedMap;
10465   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10466   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10467   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10468 }
10469
10470 /*!
10471  * This method performs the 2nd step of Partition of 2D mesh.
10472  * This method has 4 inputs :
10473  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10474  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10475  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10476  * 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'
10477  * Nodes end up lying consecutively on a cutted edge.
10478  * \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.
10479  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10480  * \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.
10481  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10482  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10483  */
10484 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10485                                            const std::vector<double>& addCoo,
10486                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10487 {
10488   int offset1=m1->getNumberOfNodes();
10489   int ncell=m2->getNumberOfCells();
10490   const int *c=m2->getNodalConnectivity()->getConstPointer();
10491   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10492   const double *coo=m2->getCoords()->getConstPointer();
10493   const double *cooBis=m1->getCoords()->getConstPointer();
10494   int offset2=offset1+m2->getNumberOfNodes();
10495   intersectEdge.resize(ncell);
10496   for(int i=0;i<ncell;i++,cI++)
10497     {
10498       const std::vector<int>& divs=subDiv[i];
10499       int nnode=cI[1]-cI[0]-1;
10500       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10501       std::map<INTERP_KERNEL::Node *, int> mapp22;
10502       for(int j=0;j<nnode;j++)
10503         {
10504           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10505           int nnid=c[(*cI)+j+1];
10506           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10507           mapp22[nn]=nnid+offset1;
10508         }
10509       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10510       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10511         ((*it).second.first)->decrRef();
10512       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10513       std::map<INTERP_KERNEL::Node *,int> mapp3;
10514       for(std::size_t j=0;j<divs.size();j++)
10515         {
10516           int id=divs[j];
10517           INTERP_KERNEL::Node *tmp=0;
10518           if(id<offset1)
10519             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10520           else if(id<offset2)
10521             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10522           else
10523             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10524           addNodes[j]=tmp;
10525           mapp3[tmp]=id;
10526         }
10527       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10528       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10529         (*it)->decrRef();
10530       e->decrRef();
10531     }
10532 }
10533
10534 /*!
10535  * 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).
10536  * 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
10537  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10538  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10539  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10540  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10541  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10542  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10543  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10544  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10545  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10546  * \param [out] cut3DSuf input/output param.
10547  */
10548 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10549                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10550                                                    const int *desc, const int *descIndx, 
10551                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10552 {
10553   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10554   int nbOf3DSurfCell=(int)cut3DSurf.size();
10555   for(int i=0;i<nbOf3DSurfCell;i++)
10556     {
10557       std::vector<int> res;
10558       int offset=descIndx[i];
10559       int nbOfSeg=descIndx[i+1]-offset;
10560       for(int j=0;j<nbOfSeg;j++)
10561         {
10562           int edgeId=desc[offset+j];
10563           int status=cut3DCurve[edgeId];
10564           if(status!=-2)
10565             {
10566               if(status>-1)
10567                 res.push_back(status);
10568               else
10569                 {
10570                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10571                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10572                 }
10573             }
10574         }
10575       switch(res.size())
10576       {
10577         case 2:
10578           {
10579             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10580             break;
10581           }
10582         case 1:
10583         case 0:
10584           {
10585             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10586             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10587             if(res.size()==2)
10588               {
10589                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10590               }
10591             else
10592               {
10593                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10594               }
10595             break;
10596           }
10597         default:
10598           {// case when plane is on a multi colinear edge of a polyhedron
10599             if((int)res.size()==2*nbOfSeg)
10600               {
10601                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10602               }
10603             else
10604               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10605           }
10606       }
10607     }
10608 }
10609
10610 /*!
10611  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10612  * 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).
10613  * 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
10614  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10615  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10616  * \param desc is the descending connectivity 3D->3DSurf
10617  * \param descIndx is the descending connectivity index 3D->3DSurf
10618  */
10619 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10620                                                   const int *desc, const int *descIndx,
10621                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10622 {
10623   checkFullyDefined();
10624   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10625     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10626   const int *nodal3D=_nodal_connec->getConstPointer();
10627   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10628   int nbOfCells=getNumberOfCells();
10629   for(int i=0;i<nbOfCells;i++)
10630     {
10631       std::map<int, std::set<int> > m;
10632       int offset=descIndx[i];
10633       int nbOfFaces=descIndx[i+1]-offset;
10634       int start=-1;
10635       int end=-1;
10636       for(int j=0;j<nbOfFaces;j++)
10637         {
10638           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10639           if(p.first!=-1 && p.second!=-1)
10640             {
10641               if(p.first!=-2)
10642                 {
10643                   start=p.first; end=p.second;
10644                   m[p.first].insert(p.second);
10645                   m[p.second].insert(p.first);
10646                 }
10647               else
10648                 {
10649                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10650                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10651                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10652                   INTERP_KERNEL::NormalizedCellType cmsId;
10653                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10654                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10655                   for(unsigned k=0;k<nbOfNodesSon;k++)
10656                     {
10657                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10658                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10659                     }
10660                 }
10661             }
10662         }
10663       if(m.empty())
10664         continue;
10665       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10666       int prev=end;
10667       while(end!=start)
10668         {
10669           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10670           const std::set<int>& s=(*it).second;
10671           std::set<int> s2; s2.insert(prev);
10672           std::set<int> s3;
10673           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10674           if(s3.size()==1)
10675             {
10676               int val=*s3.begin();
10677               conn.push_back(start);
10678               prev=start;
10679               start=val;
10680             }
10681           else
10682             start=end;
10683         }
10684       conn.push_back(end);
10685       if(conn.size()>3)
10686         {
10687           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10688           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10689           cellIds->pushBackSilent(i);
10690         }
10691     }
10692 }
10693
10694 /*!
10695  * 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
10696  * 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
10697  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10698  * 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
10699  * 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.
10700  * 
10701  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10702  */
10703 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10704 {
10705   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10706   if(sz>=4)
10707     {
10708       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10709       if(cm.getDimension()==2)
10710         {
10711           const int *node=nodalConnBg+1;
10712           int startNode=*node++;
10713           double refX=coords[2*startNode];
10714           for(;node!=nodalConnEnd;node++)
10715             {
10716               if(coords[2*(*node)]<refX)
10717                 {
10718                   startNode=*node;
10719                   refX=coords[2*startNode];
10720                 }
10721             }
10722           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10723           refX=1e300;
10724           double tmp1;
10725           double tmp2[2];
10726           double angle0=-M_PI/2;
10727           //
10728           int nextNode=-1;
10729           int prevNode=-1;
10730           double resRef;
10731           double angleNext=0.;
10732           while(nextNode!=startNode)
10733             {
10734               nextNode=-1;
10735               resRef=1e300;
10736               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10737                 {
10738                   if(*node!=tmpOut.back() && *node!=prevNode)
10739                     {
10740                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10741                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10742                       double res;
10743                       if(angleM<=angle0)
10744                         res=angle0-angleM;
10745                       else
10746                         res=angle0-angleM+2.*M_PI;
10747                       if(res<resRef)
10748                         {
10749                           nextNode=*node;
10750                           resRef=res;
10751                           angleNext=angleM;
10752                         }
10753                     }
10754                 }
10755               if(nextNode!=startNode)
10756                 {
10757                   angle0=angleNext-M_PI;
10758                   if(angle0<-M_PI)
10759                     angle0+=2*M_PI;
10760                   prevNode=tmpOut.back();
10761                   tmpOut.push_back(nextNode);
10762                 }
10763             }
10764           std::vector<int> tmp3(2*(sz-1));
10765           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10766           std::copy(nodalConnBg+1,nodalConnEnd,it);
10767           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10768             {
10769               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10770               return false;
10771             }
10772           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10773             {
10774               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10775               return false;
10776             }
10777           else
10778             {
10779               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10780               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10781               return true;
10782             }
10783         }
10784       else
10785         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10786     }
10787   else
10788     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10789 }
10790
10791 /*!
10792  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10793  * 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.
10794  * 
10795  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10796  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10797  * \param [in,out] arr array in which the remove operation will be done.
10798  * \param [in,out] arrIndx array in the remove operation will modify
10799  * \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])
10800  * \return true if \b arr and \b arrIndx have been modified, false if not.
10801  */
10802 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10803 {
10804   if(!arrIndx || !arr)
10805     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10806   if(offsetForRemoval<0)
10807     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10808   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10809   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10810   int *arrIPtr=arrIndx->getPointer();
10811   *arrIPtr++=0;
10812   int previousArrI=0;
10813   const int *arrPtr=arr->getConstPointer();
10814   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10815   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10816     {
10817       if(*arrIPtr-previousArrI>offsetForRemoval)
10818         {
10819           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10820             {
10821               if(s.find(*work)==s.end())
10822                 arrOut.push_back(*work);
10823             }
10824         }
10825       previousArrI=*arrIPtr;
10826       *arrIPtr=(int)arrOut.size();
10827     }
10828   if(arr->getNumberOfTuples()==(int)arrOut.size())
10829     return false;
10830   arr->alloc((int)arrOut.size(),1);
10831   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10832   return true;
10833 }
10834
10835 /*!
10836  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10837  * (\ref numbering-indirect).
10838  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10839  * The selection of extraction is done standardly in new2old format.
10840  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10841  *
10842  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10843  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10844  * \param [in] arrIn arr origin array from which the extraction will be done.
10845  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10846  * \param [out] arrOut the resulting array
10847  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10848  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10849  */
10850 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10851                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10852 {
10853   if(!arrIn || !arrIndxIn)
10854     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10855   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10856   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10857     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10858   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10859   const int *arrInPtr=arrIn->getConstPointer();
10860   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10861   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10862   if(nbOfGrps<0)
10863     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10864   int maxSizeOfArr=arrIn->getNumberOfTuples();
10865   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10866   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10867   arrIo->alloc((int)(sz+1),1);
10868   const int *idsIt=idsOfSelectBg;
10869   int *work=arrIo->getPointer();
10870   *work++=0;
10871   int lgth=0;
10872   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10873     {
10874       if(*idsIt>=0 && *idsIt<nbOfGrps)
10875         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10876       else
10877         {
10878           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10879           throw INTERP_KERNEL::Exception(oss.str().c_str());
10880         }
10881       if(lgth>=work[-1])
10882         *work=lgth;
10883       else
10884         {
10885           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10886           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10887           throw INTERP_KERNEL::Exception(oss.str().c_str());
10888         }
10889     }
10890   arro->alloc(lgth,1);
10891   work=arro->getPointer();
10892   idsIt=idsOfSelectBg;
10893   for(std::size_t i=0;i<sz;i++,idsIt++)
10894     {
10895       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10896         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10897       else
10898         {
10899           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10900           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10901           throw INTERP_KERNEL::Exception(oss.str().c_str());
10902         }
10903     }
10904   arrOut=arro.retn();
10905   arrIndexOut=arrIo.retn();
10906 }
10907
10908 /*!
10909  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10910  * (\ref numbering-indirect).
10911  * 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 ).
10912  * The selection of extraction is done standardly in new2old format.
10913  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10914  *
10915  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
10916  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
10917  * \param [in] idsOfSelectStep
10918  * \param [in] arrIn arr origin array from which the extraction will be done.
10919  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10920  * \param [out] arrOut the resulting array
10921  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10922  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10923  */
10924 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10925                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10926 {
10927   if(!arrIn || !arrIndxIn)
10928     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10929   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10930   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10931     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10932   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10933   const int *arrInPtr=arrIn->getConstPointer();
10934   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10935   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10936   if(nbOfGrps<0)
10937     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10938   int maxSizeOfArr=arrIn->getNumberOfTuples();
10939   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10940   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10941   arrIo->alloc((int)(sz+1),1);
10942   int idsIt=idsOfSelectStart;
10943   int *work=arrIo->getPointer();
10944   *work++=0;
10945   int lgth=0;
10946   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10947     {
10948       if(idsIt>=0 && idsIt<nbOfGrps)
10949         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10950       else
10951         {
10952           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10953           throw INTERP_KERNEL::Exception(oss.str().c_str());
10954         }
10955       if(lgth>=work[-1])
10956         *work=lgth;
10957       else
10958         {
10959           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10960           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10961           throw INTERP_KERNEL::Exception(oss.str().c_str());
10962         }
10963     }
10964   arro->alloc(lgth,1);
10965   work=arro->getPointer();
10966   idsIt=idsOfSelectStart;
10967   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10968     {
10969       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10970         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10971       else
10972         {
10973           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10974           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10975           throw INTERP_KERNEL::Exception(oss.str().c_str());
10976         }
10977     }
10978   arrOut=arro.retn();
10979   arrIndexOut=arrIo.retn();
10980 }
10981
10982 /*!
10983  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10984  * 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
10985  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10986  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10987  *
10988  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10989  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10990  * \param [in] arrIn arr origin array from which the extraction will be done.
10991  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10992  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10993  * \param [in] srcArrIndex index array of \b srcArr
10994  * \param [out] arrOut the resulting array
10995  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10996  * 
10997  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10998  */
10999 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11000                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11001                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11002 {
11003   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11004     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11005   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11006   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11007   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11008   std::vector<bool> v(nbOfTuples,true);
11009   int offset=0;
11010   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11011   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11012   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11013     {
11014       if(*it>=0 && *it<nbOfTuples)
11015         {
11016           v[*it]=false;
11017           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11018         }
11019       else
11020         {
11021           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11022           throw INTERP_KERNEL::Exception(oss.str().c_str());
11023         }
11024     }
11025   srcArrIndexPtr=srcArrIndex->getConstPointer();
11026   arrIo->alloc(nbOfTuples+1,1);
11027   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11028   const int *arrInPtr=arrIn->getConstPointer();
11029   const int *srcArrPtr=srcArr->getConstPointer();
11030   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11031   int *arroPtr=arro->getPointer();
11032   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11033     {
11034       if(v[ii])
11035         {
11036           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11037           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11038         }
11039       else
11040         {
11041           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11042           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11043           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11044         }
11045     }
11046   arrOut=arro.retn();
11047   arrIndexOut=arrIo.retn();
11048 }
11049
11050 /*!
11051  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11052  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11053  *
11054  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11055  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11056  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11057  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11058  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11059  * \param [in] srcArrIndex index array of \b srcArr
11060  * 
11061  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11062  */
11063 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11064                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11065 {
11066   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11067     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11068   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11069   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11070   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11071   int *arrInOutPtr=arrInOut->getPointer();
11072   const int *srcArrPtr=srcArr->getConstPointer();
11073   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11074     {
11075       if(*it>=0 && *it<nbOfTuples)
11076         {
11077           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11078             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11079           else
11080             {
11081               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] !";
11082               throw INTERP_KERNEL::Exception(oss.str().c_str());
11083             }
11084         }
11085       else
11086         {
11087           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11088           throw INTERP_KERNEL::Exception(oss.str().c_str());
11089         }
11090     }
11091 }
11092
11093 /*!
11094  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11095  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11096  * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 looking at arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
11097  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11098  * A negative value in \b arrIn means that it is ignored.
11099  * 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.
11100  * 
11101  * \param [in] arrIn arr origin array from which the extraction will be done.
11102  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11103  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11104  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11105  */
11106 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11107 {
11108   int seed=0,nbOfDepthPeelingPerformed=0;
11109   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11110 }
11111
11112 /*!
11113  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11114  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11115  * 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]].
11116  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11117  * A negative value in \b arrIn means that it is ignored.
11118  * 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.
11119  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11120  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11121  * \param [in] arrIn arr origin array from which the extraction will be done.
11122  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11123  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11124  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11125  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11126  * \sa MEDCouplingUMesh::partitionBySpreadZone
11127  */
11128 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11129 {
11130   nbOfDepthPeelingPerformed=0;
11131   if(!arrIndxIn)
11132     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11133   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11134   if(nbOfTuples<=0)
11135     {
11136       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11137       return ret;
11138     }
11139   //
11140   std::vector<bool> fetched(nbOfTuples,false);
11141   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11142 }
11143
11144 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11145 {
11146   nbOfDepthPeelingPerformed=0;
11147   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11148     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11149   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11150   std::vector<bool> fetched2(nbOfTuples,false);
11151   int i=0;
11152   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11153     {
11154       if(*seedElt>=0 && *seedElt<nbOfTuples)
11155         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11156       else
11157         { 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()); }
11158     }
11159   const int *arrInPtr=arrIn->getConstPointer();
11160   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11161   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11162   std::vector<int> idsToFetch1(seedBg,seedEnd);
11163   std::vector<int> idsToFetch2;
11164   std::vector<int> *idsToFetch=&idsToFetch1;
11165   std::vector<int> *idsToFetchOther=&idsToFetch2;
11166   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11167     {
11168       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11169         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11170           if(!fetched[*it2])
11171             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11172       std::swap(idsToFetch,idsToFetchOther);
11173       idsToFetchOther->clear();
11174       nbOfDepthPeelingPerformed++;
11175     }
11176   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11177   i=0;
11178   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11179   int *retPtr=ret->getPointer();
11180   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11181     if(*it)
11182       *retPtr++=i;
11183   return ret.retn();
11184 }
11185
11186 /*!
11187  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11188  * 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
11189  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11190  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11191  *
11192  * \param [in] start begin of set of ids of the input extraction (included)
11193  * \param [in] end end of set of ids of the input extraction (excluded)
11194  * \param [in] step step of the set of ids in range mode.
11195  * \param [in] arrIn arr origin array from which the extraction will be done.
11196  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11197  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11198  * \param [in] srcArrIndex index array of \b srcArr
11199  * \param [out] arrOut the resulting array
11200  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11201  * 
11202  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11203  */
11204 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11205                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11206                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11207 {
11208   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11209     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11210   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11211   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11212   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11213   int offset=0;
11214   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11215   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11216   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11217   int it=start;
11218   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11219     {
11220       if(it>=0 && it<nbOfTuples)
11221         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11222       else
11223         {
11224           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11225           throw INTERP_KERNEL::Exception(oss.str().c_str());
11226         }
11227     }
11228   srcArrIndexPtr=srcArrIndex->getConstPointer();
11229   arrIo->alloc(nbOfTuples+1,1);
11230   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11231   const int *arrInPtr=arrIn->getConstPointer();
11232   const int *srcArrPtr=srcArr->getConstPointer();
11233   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11234   int *arroPtr=arro->getPointer();
11235   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11236     {
11237       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11238       if(pos<0)
11239         {
11240           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11241           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11242         }
11243       else
11244         {
11245           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11246           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11247         }
11248     }
11249   arrOut=arro.retn();
11250   arrIndexOut=arrIo.retn();
11251 }
11252
11253 /*!
11254  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11255  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11256  *
11257  * \param [in] start begin of set of ids of the input extraction (included)
11258  * \param [in] end end of set of ids of the input extraction (excluded)
11259  * \param [in] step step of the set of ids in range mode.
11260  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11261  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11262  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11263  * \param [in] srcArrIndex index array of \b srcArr
11264  * 
11265  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11266  */
11267 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11268                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11269 {
11270   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11271     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11272   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11273   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11274   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11275   int *arrInOutPtr=arrInOut->getPointer();
11276   const int *srcArrPtr=srcArr->getConstPointer();
11277   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11278   int it=start;
11279   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11280     {
11281       if(it>=0 && it<nbOfTuples)
11282         {
11283           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11284             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11285           else
11286             {
11287               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11288               throw INTERP_KERNEL::Exception(oss.str().c_str());
11289             }
11290         }
11291       else
11292         {
11293           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11294           throw INTERP_KERNEL::Exception(oss.str().c_str());
11295         }
11296     }
11297 }
11298
11299 /*!
11300  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11301  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11302  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11303  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11304  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11305  * 
11306  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11307  */
11308 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11309 {
11310   checkFullyDefined();
11311   int mdim=getMeshDimension();
11312   int spaceDim=getSpaceDimension();
11313   if(mdim!=spaceDim)
11314     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11315   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11316   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11317   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11318   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11319   ret->setCoords(getCoords());
11320   ret->allocateCells((int)partition.size());
11321   //
11322   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11323     {
11324       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11325       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11326       switch(mdim)
11327       {
11328         case 2:
11329           cell=tmp->buildUnionOf2DMesh();
11330           break;
11331         case 3:
11332           cell=tmp->buildUnionOf3DMesh();
11333           break;
11334         default:
11335           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11336       }
11337
11338       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11339     }
11340   //
11341   ret->finishInsertingCells();
11342   return ret.retn();
11343 }
11344
11345 /*!
11346  * This method partitions \b this into contiguous zone.
11347  * This method only needs a well defined connectivity. Coordinates are not considered here.
11348  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11349  */
11350 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11351 {
11352   int nbOfCellsCur=getNumberOfCells();
11353   std::vector<DataArrayInt *> ret;
11354   if(nbOfCellsCur<=0)
11355     return ret;
11356   DataArrayInt *neigh=0,*neighI=0;
11357   computeNeighborsOfCells(neigh,neighI);
11358   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11359   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11360   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11361   int seed=0;
11362   while(seed<nbOfCellsCur)
11363     {
11364       int nbOfPeelPerformed=0;
11365       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11366       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11367     }
11368   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11369     ret.push_back((*it).retn());
11370   return ret;
11371 }
11372
11373 /*!
11374  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11375  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11376  *
11377  * \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.
11378  * \return a newly allocated DataArrayInt to be managed by the caller.
11379  * \throw In case of \a code has not the right format (typically of size 3*n)
11380  */
11381 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11382 {
11383   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11384   std::size_t nb=code.size()/3;
11385   if(code.size()%3!=0)
11386     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11387   ret->alloc((int)nb,2);
11388   int *retPtr=ret->getPointer();
11389   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11390     {
11391       retPtr[0]=code[3*i+2];
11392       retPtr[1]=code[3*i+2]+code[3*i+1];
11393     }
11394   return ret.retn();
11395 }
11396
11397 /*!
11398  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11399  * All cells in \a this are expected to be linear 3D cells.
11400  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11401  * It leads to an increase to number of cells.
11402  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11403  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11404  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11405  *
11406  * \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.
11407  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11408  * \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. 
11409  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11410  *          an id of old cell producing it. The caller is to delete this array using
11411  *         decrRef() as it is no more needed.
11412  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11413  *
11414  * \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
11415  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11416  * 
11417  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11418  * \throw If \a this is not fully constituted with linear 3D cells.
11419  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11420  */
11421 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11422 {
11423   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11424   checkConnectivityFullyDefined();
11425   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11426     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11427   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11428   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11429   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11430   int *retPt(ret->getPointer());
11431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11432   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11433   const int *oldc(_nodal_connec->begin());
11434   const int *oldci(_nodal_connec_index->begin());
11435   const double *coords(_coords->begin());
11436   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11437     {
11438       std::vector<int> a; std::vector<double> b;
11439       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11440       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11441       const int *aa(&a[0]);
11442       if(!b.empty())
11443         {
11444           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11445             if(*it<0)
11446               *it=(-(*(it))-1+nbNodes);
11447           addPts->insertAtTheEnd(b.begin(),b.end());
11448           nbNodes+=(int)b.size()/3;
11449         }
11450       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11451         newConn->insertAtTheEnd(aa,aa+4);
11452     }
11453   if(!addPts->empty())
11454     {
11455       addPts->rearrange(3);
11456       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11457       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11458       ret0->setCoords(addPts);
11459     }
11460   else
11461     {
11462       nbOfAdditionalPoints=0;
11463       ret0->setCoords(getCoords());
11464     }
11465   ret0->setNodalConnectivity(newConn);
11466   //
11467   ret->computeOffsets2();
11468   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11469   return ret0.retn();
11470 }
11471
11472 /*!
11473  * 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). 
11474  *
11475  * \sa MEDCouplingUMesh::split2DCells
11476  */
11477 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11478 {
11479   checkConnectivityFullyDefined();
11480   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11481   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11482   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11483   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11484   int prevPosOfCi(ciPtr[0]);
11485   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11486     {
11487       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11488       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11489       for(int j=0;j<sz;j++)
11490         {
11491           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11492           for(int k=0;k<sz2;k++)
11493             *cPtr++=subPtr[offset2+k];
11494           if(j!=sz-1)
11495             *cPtr++=oldConn[prevPosOfCi+j+2];
11496           deltaSz+=sz2;
11497         }
11498       prevPosOfCi=ciPtr[1];
11499       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11500     }
11501   if(c->end()!=cPtr)
11502     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11503   _nodal_connec->decrRef();
11504   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11505 }
11506
11507 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11508 {
11509   if(id!=-1)
11510     return id;
11511   else
11512     {
11513       int ret(nodesCnter++);
11514       double newPt[2];
11515       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11516       addCoo.insertAtTheEnd(newPt,newPt+2);
11517       return ret;
11518     }
11519 }
11520
11521 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11522 {
11523   if(id!=-1)
11524     return id;
11525   else
11526     {
11527       int ret(nodesCnter++);
11528       double newPt[2];
11529       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11530       addCoo.insertAtTheEnd(newPt,newPt+2);
11531       return ret;
11532     }
11533 }
11534
11535
11536 /// @cond INTERNAL
11537
11538 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)
11539 {
11540   int tmp[3];
11541   int trueStart(start>=0?start:nbOfEdges+start);
11542   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11543   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11544   if(linOrArc)
11545     {
11546       if(stp-start>1)
11547         {
11548           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11549           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11550           middles.push_back(tmp3+offset);
11551         }
11552       else
11553         middles.push_back(connBg[trueStart+nbOfEdges]);
11554     }
11555 }
11556
11557 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)
11558 {
11559   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11560   newConnOfCell->pushBackSilent(tmpEnd);
11561   if(linOrArc)
11562     {
11563       if(stp-start>1)
11564         {
11565           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11566           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11567           middles.push_back(tmp3+offset);
11568         }
11569       else
11570         middles.push_back(connBg[start+nbOfEdges]);
11571     }
11572 }
11573
11574 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)
11575 {
11576   // only the quadratic point to deal with:
11577   if(linOrArc)
11578     {
11579       if(stp-start>1)
11580         {
11581           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11582           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11583           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11584           middles.push_back(tmp3+offset);
11585         }
11586       else
11587         middles.push_back(connBg[start+nbOfEdges]);
11588     }
11589 }
11590
11591 /// @endcond
11592
11593 /*!
11594  * 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 ) .
11595  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11596  */
11597 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11598 {
11599   std::size_t sz(std::distance(connBg,connEnd));
11600   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11601     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11602   sz--;
11603   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11604   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11605   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11606   unsigned nbOfHit(0); // number of fusions operated
11607   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11608   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
11609   INTERP_KERNEL::NormalizedCellType typeOfSon;
11610   std::vector<int> middles;
11611   bool ret(false);
11612   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11613     {
11614       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11615       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11616       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11617       posEndElt = posBaseElt+1;
11618
11619       // Look backward first: are the final edges of the cells colinear with the first ones?
11620       // This initializes posBaseElt.
11621       if(nbOfTurn==0)
11622         {
11623           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11624             {
11625               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11626               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11627               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11628               bool isColinear=eint->areColinears();
11629               if(isColinear)
11630                 {
11631                   nbOfHit++;
11632                   posBaseElt--;
11633                   ret=true;
11634                 }
11635               delete eint;
11636               eCand->decrRef();
11637               if(!isColinear)
11638                 break;
11639             }
11640         }
11641       // Now move forward:
11642       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11643       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11644         {
11645           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11646           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11647           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11648           bool isColinear(eint->areColinears());
11649           if(isColinear)
11650             {
11651               nbOfHit++;
11652               posEndElt++;
11653               ret=true;
11654             }
11655           delete eint;
11656           eCand->decrRef();
11657           if(!isColinear)
11658               break;
11659         }
11660       //push [posBaseElt,posEndElt) in newConnOfCell using e
11661       // 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!
11662       if(nbOfTurn==0)
11663         // at the begining of the connectivity (insert type)
11664         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11665       else if((nbOfHit+nbOfTurn) != (nbs-1))
11666         // in the middle
11667         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11668       if ((nbOfHit+nbOfTurn) == (nbs-1))
11669         // at the end (only quad points to deal with)
11670         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11671       posBaseElt=posEndElt;
11672       e->decrRef();
11673     }
11674   if(!middles.empty())
11675     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11676   return ret;
11677 }
11678
11679 /*!
11680  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11681  *
11682  * \return  int - the number of new nodes created.
11683  * \sa MEDCouplingUMesh::split2DCells
11684  */
11685 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11686 {
11687   checkCoherency();
11688   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11689   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11690   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11691   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11692   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11693   const double *oldCoordsPtr(getCoords()->begin());
11694   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11695   int prevPosOfCi(ciPtr[0]);
11696   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11697     {
11698       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11699       for(int j=0;j<sz;j++)
11700         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11701       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11702       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11703         {
11704           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11705           if(sz2==0)
11706             {
11707               if(j<sz-1)
11708                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11709               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11710               continue;
11711             }
11712           std::vector<INTERP_KERNEL::Node *> ns(3);
11713           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11714           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11715           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11716           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11717           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11718             {
11719               cPtr[1]=subPtr[offset2+k];
11720               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11721             }
11722           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11723           if(j!=sz-1)
11724             { cPtr[1]=tmpEnd; }
11725           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11726         }
11727       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11728       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11729     }
11730   if(c->end()!=cPtr)
11731     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11732   _nodal_connec->decrRef();
11733   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11734   addCoo->rearrange(2);
11735   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11736   setCoords(coo);
11737   return addCoo->getNumberOfTuples();
11738 }
11739
11740 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11741 {
11742   if(nodalConnec && nodalConnecIndex)
11743     {
11744       types.clear();
11745       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11746       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11747       if(nbOfElem>0)
11748         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11749           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11750     }
11751 }
11752
11753 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11754     _own_cell(true),_cell_id(-1),_nb_cell(0)
11755 {
11756   if(mesh)
11757     {
11758       mesh->incrRef();
11759       _nb_cell=mesh->getNumberOfCells();
11760     }
11761 }
11762
11763 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11764 {
11765   if(_mesh)
11766     _mesh->decrRef();
11767   if(_own_cell)
11768     delete _cell;
11769 }
11770
11771 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11772     _own_cell(false),_cell_id(bg-1),
11773     _nb_cell(end)
11774 {
11775   if(mesh)
11776     mesh->incrRef();
11777 }
11778
11779 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11780 {
11781   _cell_id++;
11782   if(_cell_id<_nb_cell)
11783     {
11784       _cell->next();
11785       return _cell;
11786     }
11787   else
11788     return 0;
11789 }
11790
11791 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11792 {
11793   if(_mesh)
11794     _mesh->incrRef();
11795 }
11796
11797 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11798 {
11799   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11800 }
11801
11802 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11803 {
11804   if(_mesh)
11805     _mesh->decrRef();
11806 }
11807
11808 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11809     _itc(itc),
11810     _bg(bg),_end(end)
11811 {
11812   if(_mesh)
11813     _mesh->incrRef();
11814 }
11815
11816 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11817 {
11818   if(_mesh)
11819     _mesh->decrRef();
11820 }
11821
11822 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11823 {
11824   return _type;
11825 }
11826
11827 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11828 {
11829   return _end-_bg;
11830 }
11831
11832 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11833 {
11834   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11835 }
11836
11837 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11838 {
11839   if(mesh)
11840     {
11841       mesh->incrRef();
11842       _nb_cell=mesh->getNumberOfCells();
11843     }
11844 }
11845
11846 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11847 {
11848   if(_mesh)
11849     _mesh->decrRef();
11850   delete _cell;
11851 }
11852
11853 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11854 {
11855   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11856   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11857   if(_cell_id<_nb_cell)
11858     {
11859       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11860       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11861       int startId=_cell_id;
11862       _cell_id+=nbOfElems;
11863       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11864     }
11865   else
11866     return 0;
11867 }
11868
11869 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11870 {
11871   if(mesh)
11872     {
11873       _conn=mesh->getNodalConnectivity()->getPointer();
11874       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11875     }
11876 }
11877
11878 void MEDCouplingUMeshCell::next()
11879 {
11880   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11881     {
11882       _conn+=_conn_lgth;
11883       _conn_indx++;
11884     }
11885   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11886 }
11887
11888 std::string MEDCouplingUMeshCell::repr() const
11889 {
11890   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11891     {
11892       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11893       oss << " : ";
11894       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11895       return oss.str();
11896     }
11897   else
11898     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11899 }
11900
11901 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11902 {
11903   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11904     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11905   else
11906     return INTERP_KERNEL::NORM_ERROR;
11907 }
11908
11909 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11910 {
11911   lgth=_conn_lgth;
11912   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11913     return _conn;
11914   else
11915     return 0;
11916 }