Salome HOME
debugs
[modules/med.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2013  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.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMeshQuality.hxx"
34 #include "InterpKernelCellSimplify.hxx"
35 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
36 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
42
43 #include <sstream>
44 #include <fstream>
45 #include <numeric>
46 #include <cstring>
47 #include <limits>
48 #include <list>
49
50 using namespace ParaMEDMEM;
51
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53
54 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 };
55
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 {
58   return new MEDCouplingUMesh;
59 }
60
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
62 {
63   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64   ret->setName(meshName);
65   ret->setMeshDimension(meshDim);
66   return ret;
67 }
68
69 /*!
70  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71  * between \a this and the new mesh.
72  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73  *          delete this mesh using decrRef() as it is no more needed. 
74  */
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
76 {
77   return clone(true);
78 }
79
80 /*!
81  * Returns a new MEDCouplingMesh which is a copy of \a this one.
82  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83  * this mesh are shared by the new mesh.
84  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85  *          delete this mesh using decrRef() as it is no more needed. 
86  */
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
88 {
89   return new MEDCouplingUMesh(*this,recDeepCpy);
90 }
91
92 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other) throw(INTERP_KERNEL::Exception)
93 {
94   if(!other)
95     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
96   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
97   if(!otherC)
98     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
99   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
100   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
101 }
102
103 std::size_t MEDCouplingUMesh::getHeapMemorySize() const
104 {
105   std::size_t ret=0;
106   if(_nodal_connec)
107     ret+=_nodal_connec->getHeapMemorySize();
108   if(_nodal_connec_index)
109     ret+=_nodal_connec_index->getHeapMemorySize();
110   return MEDCouplingPointSet::getHeapMemorySize()+ret;
111 }
112
113 void MEDCouplingUMesh::updateTime() const
114 {
115   MEDCouplingPointSet::updateTime();
116   if(_nodal_connec)
117     {
118       updateTimeWith(*_nodal_connec);
119     }
120   if(_nodal_connec_index)
121     {
122       updateTimeWith(*_nodal_connec_index);
123     }
124 }
125
126 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
127 {
128 }
129
130 /*!
131  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
132  * then \a this mesh is most probably is writable, exchangeable and available for most
133  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
134  * this method to check that all is in order with \a this mesh.
135  *  \throw If the mesh dimension is not set.
136  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
137  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
138  *  \throw If the connectivity data array has more than one component.
139  *  \throw If the connectivity data array has a named component.
140  *  \throw If the connectivity index data array has more than one component.
141  *  \throw If the connectivity index data array has a named component.
142  */
143 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
144 {
145   if(_mesh_dim<-1)
146    throw INTERP_KERNEL::Exception("No mesh dimension specified !");
147   if(_mesh_dim!=-1)
148     MEDCouplingPointSet::checkCoherency();
149   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
150     {
151       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
152         {
153           std::ostringstream message;
154           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
155           throw INTERP_KERNEL::Exception(message.str().c_str());
156         }
157     }
158   if(_nodal_connec)
159     {
160       if(_nodal_connec->getNumberOfComponents()!=1)
161         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
162       if(_nodal_connec->getInfoOnComponent(0)!="")
163         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
164     }
165   else
166     if(_mesh_dim!=-1)
167       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
168   if(_nodal_connec_index)
169     {
170       if(_nodal_connec_index->getNumberOfComponents()!=1)
171         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
172       if(_nodal_connec_index->getInfoOnComponent(0)!="")
173         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
174     }
175   else
176     if(_mesh_dim!=-1)
177       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
178 }
179
180 /*!
181  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
182  * then \a this mesh is most probably is writable, exchangeable and available for all
183  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
184  * method thoroughly checks the nodal connectivity.
185  *  \param [in] eps - a not used parameter.
186  *  \throw If the mesh dimension is not set.
187  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
188  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
189  *  \throw If the connectivity data array has more than one component.
190  *  \throw If the connectivity data array has a named component.
191  *  \throw If the connectivity index data array has more than one component.
192  *  \throw If the connectivity index data array has a named component.
193  *  \throw If number of nodes defining an element does not correspond to the type of element.
194  *  \throw If the nodal connectivity includes an invalid node id.
195  */
196 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
197 {
198   checkCoherency();
199   if(_mesh_dim==-1)
200     return ;
201   int meshDim=getMeshDimension();
202   int nbOfNodes=getNumberOfNodes();
203   int nbOfCells=getNumberOfCells();
204   const int *ptr=_nodal_connec->getConstPointer();
205   const int *ptrI=_nodal_connec_index->getConstPointer();
206   for(int i=0;i<nbOfCells;i++)
207     {
208       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
209       if((int)cm.getDimension()!=meshDim)
210         {
211           std::ostringstream oss;
212           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
213           throw INTERP_KERNEL::Exception(oss.str().c_str());
214         }
215       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
216       if(!cm.isDynamic())
217         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
218           {
219             std::ostringstream oss;
220             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
221             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
222             throw INTERP_KERNEL::Exception(oss.str().c_str());
223           }
224       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
225         {
226           int nodeId=*w;
227           if(nodeId>=0)
228             {
229               if(nodeId>=nbOfNodes)
230                 {
231                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
232                   throw INTERP_KERNEL::Exception(oss.str().c_str());
233                 }
234             }
235           else if(nodeId<-1)
236             {
237               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
238               throw INTERP_KERNEL::Exception(oss.str().c_str());
239             }
240           else
241             {
242               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
243                 {
244                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
245                   throw INTERP_KERNEL::Exception(oss.str().c_str());
246                 }
247             }
248         }
249     }
250 }
251
252
253 /*!
254  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
255  * then \a this mesh is most probably is writable, exchangeable and available for all
256  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
257  *  \param [in] eps - a not used parameter.
258  *  \throw If the mesh dimension is not set.
259  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
260  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
261  *  \throw If the connectivity data array has more than one component.
262  *  \throw If the connectivity data array has a named component.
263  *  \throw If the connectivity index data array has more than one component.
264  *  \throw If the connectivity index data array has a named component.
265  *  \throw If number of nodes defining an element does not correspond to the type of element.
266  *  \throw If the nodal connectivity includes an invalid node id.
267  */
268 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
269 {
270   checkCoherency1(eps);
271 }
272
273 /*!
274  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
275  * elements contained in the mesh. For more info on the mesh dimension see
276  * \ref MEDCouplingUMeshPage.
277  *  \param [in] meshDim - a new mesh dimension.
278  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
279  */
280 void MEDCouplingUMesh::setMeshDimension(int meshDim)
281 {
282   if(meshDim<-1 || meshDim>3)
283     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
284   _mesh_dim=meshDim;
285   declareAsNew();
286 }
287
288 /*!
289  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
290  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
291  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
292  *
293  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
294  *
295  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
296  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
297  */
298 void MEDCouplingUMesh::allocateCells(int nbOfCells)
299 {
300   if(nbOfCells<0)
301     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
302   if(_nodal_connec_index)
303     {
304       _nodal_connec_index->decrRef();
305     }
306   if(_nodal_connec)
307     {
308       _nodal_connec->decrRef();
309     }
310   _nodal_connec_index=DataArrayInt::New();
311   _nodal_connec_index->reserve(nbOfCells+1);
312   _nodal_connec_index->pushBackSilent(0);
313   _nodal_connec=DataArrayInt::New();
314   _nodal_connec->reserve(2*nbOfCells);
315   _types.clear();
316   declareAsNew();
317 }
318
319 /*!
320  * Appends a cell to the connectivity array. For deeper understanding what is
321  * happening see \ref MEDCouplingUMeshNodalConnectivity.
322  *  \param [in] type - type of cell to add.
323  *  \param [in] size - number of nodes constituting this cell.
324  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
325  * 
326  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
327  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
328  */
329 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
330 {
331   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
332   if(_nodal_connec_index==0)
333     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
334   if((int)cm.getDimension()==_mesh_dim)
335     {
336       if(!cm.isDynamic())
337         if(size!=(int)cm.getNumberOfNodes())
338           {
339             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
340             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
341             throw INTERP_KERNEL::Exception(oss.str().c_str());
342           }
343       int idx=_nodal_connec_index->back();
344       int val=idx+size+1;
345       _nodal_connec_index->pushBackSilent(val);
346       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
347       _types.insert(type);
348     }
349   else
350     {
351       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
352       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
353       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
354       throw INTERP_KERNEL::Exception(oss.str().c_str());
355     }
356 }
357
358 /*!
359  * Compacts data arrays to release unused memory. This method is to be called after
360  * finishing cell insertion using \a this->insertNextCell().
361  * 
362  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
363  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
364  */
365 void MEDCouplingUMesh::finishInsertingCells()
366 {
367   _nodal_connec->pack();
368   _nodal_connec_index->pack();
369   _nodal_connec->declareAsNew();
370   _nodal_connec_index->declareAsNew();
371   updateTime();
372 }
373
374 /*!
375  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
376  * Useful for python users.
377  */
378 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
379 {
380   return new MEDCouplingUMeshCellIterator(this);
381 }
382
383 /*!
384  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
385  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
386  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
387  * Useful for python users.
388  */
389 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
390 {
391   if(!checkConsecutiveCellTypes())
392     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
393   return new MEDCouplingUMeshCellByTypeEntry(this);
394 }
395
396 /*!
397  * Returns a set of all cell types available in \a this mesh.
398  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
399  * \warning this method does not throw any exception even if \a this is not defined.
400  */
401 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
402 {
403   return _types;
404 }
405
406 /*!
407  * This method is a method that compares \a this and \a other.
408  * This method compares \b all attributes, even names and component names.
409  */
410 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
411 {
412   if(!other)
413     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
414   std::ostringstream oss; oss.precision(15);
415   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
416   if(!otherC)
417     {
418       reason="mesh given in input is not castable in MEDCouplingUMesh !";
419       return false;
420     }
421   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
422     return false;
423   if(_mesh_dim!=otherC->_mesh_dim)
424     {
425       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
426       reason=oss.str();
427       return false;
428     }
429   if(_types!=otherC->_types)
430     {
431       oss << "umesh geometric type mismatch :\nThis geometric types are :";
432       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
433         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
434       oss << "\nOther geometric types are :";
435       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
436         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
437       reason=oss.str();
438       return false;
439     }
440   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
441     if(_nodal_connec==0 || otherC->_nodal_connec==0)
442       {
443         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
444         return false;
445       }
446   if(_nodal_connec!=otherC->_nodal_connec)
447     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
448       {
449         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
450         return false;
451       }
452   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
453     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
454       {
455         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
456         return false;
457       }
458   if(_nodal_connec_index!=otherC->_nodal_connec_index)
459     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
460       {
461         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
462         return false;
463       }
464   return true;
465 }
466
467 /*!
468  * Checks if data arrays of this mesh (node coordinates, nodal
469  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
470  * not considered.
471  *  \param [in] other - the mesh to compare with.
472  *  \param [in] prec - precision value used to compare node coordinates.
473  *  \return bool - \a true if the two meshes are same.
474  */
475 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
476 {
477   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
478   if(!otherC)
479     return false;
480   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
481     return false;
482   if(_mesh_dim!=otherC->_mesh_dim)
483     return false;
484   if(_types!=otherC->_types)
485     return false;
486   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
487     if(_nodal_connec==0 || otherC->_nodal_connec==0)
488       return false;
489   if(_nodal_connec!=otherC->_nodal_connec)
490     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
491       return false;
492   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
493     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
494       return false;
495   if(_nodal_connec_index!=otherC->_nodal_connec_index)
496     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
497       return false;
498   return true;
499 }
500
501 /*!
502  * Checks if \a this and \a other meshes are geometrically equivalent with high
503  * probability, else an exception is thrown. The meshes are considered equivalent if
504  * (1) meshes contain the same number of nodes and the same number of elements of the
505  * same types (2) three cells of the two meshes (first, last and middle) are based
506  * on coincident nodes (with a specified precision).
507  *  \param [in] other - the mesh to compare with.
508  *  \param [in] prec - the precision used to compare nodes of the two meshes.
509  *  \throw If the two meshes do not match.
510  */
511 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
512 {
513  MEDCouplingPointSet::checkFastEquivalWith(other,prec);
514  const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
515   if(!otherC)
516     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
517 }
518
519 /*!
520  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
521  * cells each node belongs to.
522  * \warning For speed reasons, this method does not check if node ids in the nodal
523  *          connectivity correspond to the size of node coordinates array.
524  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
525  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
526  *        dividing cell ids in \a revNodal into groups each referring to one
527  *        node. Its every element (except the last one) is an index pointing to the
528  *         first id of a group of cells. For example cells sharing the node #1 are 
529  *        described by following range of indices: 
530  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
531  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
532  *        Number of cells sharing the *i*-th node is
533  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
534  * \throw If the coordinates array is not set.
535  * \throw If the nodal connectivity of cells is not defined.
536  * 
537  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
538  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
539  */
540 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
541 {
542   checkFullyDefined();
543   int nbOfNodes=getNumberOfNodes();
544   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
545   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
546   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
547   const int *conn=_nodal_connec->getConstPointer();
548   const int *connIndex=_nodal_connec_index->getConstPointer();
549   int nbOfCells=getNumberOfCells();
550   int nbOfEltsInRevNodal=0;
551   for(int eltId=0;eltId<nbOfCells;eltId++)
552     {
553       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
554       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
555       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
556         if(*iter>=0)//for polyhedrons
557           {
558             nbOfEltsInRevNodal++;
559             revNodalIndxPtr[(*iter)+1]++;
560           }
561     }
562   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
563   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
564   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
565   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
566   for(int eltId=0;eltId<nbOfCells;eltId++)
567     {
568       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
569       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
570       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
571         if(*iter>=0)//for polyhedrons
572           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
573     }
574 }
575
576 /// @cond INTERNAL
577
578 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
579 {
580   return id;
581 }
582
583 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
584 {
585   if(!compute)
586     return id+1;
587   else
588     {
589       if(cm.getOrientationStatus(nb,conn1,conn2))
590         return id+1;
591       else
592         return -(id+1);
593     }
594 }
595
596 class MinusOneSonsGenerator
597 {
598 public:
599   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
600   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
601   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
602   static const int DELTA=1;
603 private:
604   const INTERP_KERNEL::CellModel& _cm;
605 };
606
607 class MinusOneSonsGeneratorBiQuadratic
608 {
609 public:
610   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
611   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
612   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
613   static const int DELTA=1;
614 private:
615   const INTERP_KERNEL::CellModel& _cm;
616 };
617
618 class MinusTwoSonsGenerator
619 {
620 public:
621   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
622   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
623   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
624   static const int DELTA=2;
625 private:
626   const INTERP_KERNEL::CellModel& _cm;
627 };
628
629 /// @endcond
630
631 /*!
632  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
633  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
634  * describing correspondence between cells of \a this and the result meshes are
635  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
636  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
637  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
638  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
639  * \warning For speed reasons, this method does not check if node ids in the nodal
640  *          connectivity correspond to the size of node coordinates array.
641  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
642  *          to write this mesh to the MED file, its cells must be sorted using
643  *          sortCellsInMEDFileFrmt().
644  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
645  *         each cell of \a this mesh.
646  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
647  *        dividing cell ids in \a desc into groups each referring to one
648  *        cell of \a this mesh. Its every element (except the last one) is an index
649  *        pointing to the first id of a group of cells. For example cells of the
650  *        result mesh bounding the cell #1 of \a this mesh are described by following
651  *        range of indices:
652  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
653  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
654  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
655  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
656  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
657  *         by each cell of the result mesh.
658  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
659  *        in the result mesh,
660  *        dividing cell ids in \a revDesc into groups each referring to one
661  *        cell of the result mesh the same way as \a descIndx divides \a desc.
662  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
663  *        delete this mesh using decrRef() as it is no more needed.
664  *  \throw If the coordinates array is not set.
665  *  \throw If the nodal connectivity of cells is node defined.
666  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
667  *         revDescIndx == NULL.
668  * 
669  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
670  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
671  * \sa buildDescendingConnectivity2()
672  */
673 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
674 {
675   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
676 }
677
678 /*!
679  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
680  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
681  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
682  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
683  * \sa MEDCouplingUMesh::buildDescendingConnectivity
684  */
685 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
686 {
687   checkFullyDefined();
688   if(getMeshDimension()!=3)
689     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
690   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
691 }
692
693 /*!
694  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
695  * this->getMeshDimension(), that bound cells of \a this mesh. In
696  * addition arrays describing correspondence between cells of \a this and the result
697  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
698  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
699  *  mesh. This method differs from buildDescendingConnectivity() in that apart
700  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
701  * result meshes. So a positive id means that order of nodes in corresponding cells
702  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
703  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
704  * i.e. cell ids are one-based.
705  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
706  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
707  * \warning For speed reasons, this method does not check if node ids in the nodal
708  *          connectivity correspond to the size of node coordinates array.
709  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
710  *          to write this mesh to the MED file, its cells must be sorted using
711  *          sortCellsInMEDFileFrmt().
712  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
713  *         each cell of \a this mesh.
714  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
715  *        dividing cell ids in \a desc into groups each referring to one
716  *        cell of \a this mesh. Its every element (except the last one) is an index
717  *        pointing to the first id of a group of cells. For example cells of the
718  *        result mesh bounding the cell #1 of \a this mesh are described by following
719  *        range of indices:
720  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
721  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
722  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
723  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
724  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
725  *         by each cell of the result mesh.
726  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
727  *        in the result mesh,
728  *        dividing cell ids in \a revDesc into groups each referring to one
729  *        cell of the result mesh the same way as \a descIndx divides \a desc.
730  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
731  *        shares the node coordinates array with \a this mesh. The caller is to
732  *        delete this mesh using decrRef() as it is no more needed.
733  *  \throw If the coordinates array is not set.
734  *  \throw If the nodal connectivity of cells is node defined.
735  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
736  *         revDescIndx == NULL.
737  * 
738  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
739  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
740  * \sa buildDescendingConnectivity()
741  */
742 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
743 {
744   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
745 }
746
747 /*!
748  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
749  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
750  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
751  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
752  *
753  * \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
754  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
755  * \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.
756  */
757 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
758 {
759   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
761   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
762   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
763   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
764   meshDM1=0;
765   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
766 }
767
768 /*!
769  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
770  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
771  * excluding a set of meshdim-1 cells in input descending connectivity.
772  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
773  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
774  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
775  *
776  * \param [in] desc descending connectivity array.
777  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
778  * \param [in] revDesc reverse descending connectivity array.
779  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
780  * \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
781  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
782  * \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.
783  */
784 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
785                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
786 {
787   if(!desc || !descIndx || !revDesc || !revDescIndx)
788     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
789   const int *descPtr=desc->getConstPointer();
790   const int *descIPtr=descIndx->getConstPointer();
791   const int *revDescPtr=revDesc->getConstPointer();
792   const int *revDescIPtr=revDescIndx->getConstPointer();
793   //
794   int nbCells=descIndx->getNumberOfTuples()-1;
795   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
796   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
797   int *out1Ptr=out1->getPointer();
798   *out1Ptr++=0;
799   out0->reserve(desc->getNumberOfTuples());
800   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
801     {
802       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
803         {
804           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
805           s.erase(i);
806           out0->insertAtTheEnd(s.begin(),s.end());
807         }
808       *out1Ptr=out0->getNumberOfTuples();
809     }
810   neighbors=out0.retn();
811   neighborsIndx=out1.retn();
812 }
813
814 /// @cond INTERNAL
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.
819  */
820 template<class SonsGenerator>
821 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
822 {
823   if(!desc || !descIndx || !revDesc || !revDescIndx)
824     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
825   checkConnectivityFullyDefined();
826   int nbOfCells=getNumberOfCells();
827   int nbOfNodes=getNumberOfNodes();
828   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
829   int *revNodalIndxPtr=revNodalIndx->getPointer();
830   const int *conn=_nodal_connec->getConstPointer();
831   const int *connIndex=_nodal_connec_index->getConstPointer();
832   std::string name="Mesh constituent of "; name+=getName();
833   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
834   ret->setCoords(getCoords());
835   ret->allocateCells(2*nbOfCells);
836   descIndx->alloc(nbOfCells+1,1);
837   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
838   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
839   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
840     {
841       int pos=connIndex[eltId];
842       int posP1=connIndex[eltId+1];
843       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
844       SonsGenerator sg(cm);
845       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
846       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
847       for(unsigned i=0;i<nbOfSons;i++)
848         {
849           INTERP_KERNEL::NormalizedCellType cmsId;
850           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
851           for(unsigned k=0;k<nbOfNodesSon;k++)
852             if(tmp[k]>=0)
853               revNodalIndxPtr[tmp[k]+1]++;
854           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
855           revDesc2->pushBackSilent(eltId);
856         }
857       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
858     }
859   int nbOfCellsM1=ret->getNumberOfCells();
860   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
861   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
862   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
863   int *revNodalPtr=revNodal->getPointer();
864   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
865   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
866   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
867     {
868       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
869       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
870       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
871         if(*iter>=0)//for polyhedrons
872           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
873     }
874   //
875   DataArrayInt *commonCells=0,*commonCellsI=0;
876   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
878   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
879   int newNbOfCellsM1=-1;
880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
881                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
882   std::vector<bool> isImpacted(nbOfCellsM1,false);
883   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
884     for(int work2=work[0];work2!=work[1];work2++)
885       isImpacted[commonCellsPtr[work2]]=true;
886   const int *o2nM1Ptr=o2nM1->getConstPointer();
887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
888   const int *n2oM1Ptr=n2oM1->getConstPointer();
889   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
890   ret2->copyTinyInfoFrom(this);
891   desc->alloc(descIndx->back(),1);
892   int *descPtr=desc->getPointer();
893   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
894   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
895     {
896       if(!isImpacted[i])
897         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
898       else
899         {
900           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
901             {
902               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
903               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
904             }
905           else
906             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
907         }
908     }
909   revDesc->reserve(newNbOfCellsM1);
910   revDescIndx->alloc(newNbOfCellsM1+1,1);
911   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
912   const int *revDesc2Ptr=revDesc2->getConstPointer();
913   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
914     {
915       int oldCellIdM1=n2oM1Ptr[i];
916       if(!isImpacted[oldCellIdM1])
917         {
918           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
919           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
920         }
921       else
922         {
923           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
924             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
925           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
926           commonCellsIPtr++;
927         }
928     }
929   //
930   return ret2.retn();
931 }
932
933 struct MEDCouplingAccVisit
934 {
935   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
936   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
937   int _new_nb_of_nodes;
938 };
939
940 /// @endcond
941
942 /*!
943  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
944  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
945  * array of cell ids. Pay attention that after conversion all algorithms work slower
946  * with \a this mesh than before conversion. <br> If an exception is thrown during the
947  * conversion due presence of invalid ids in the array of cells to convert, as a
948  * result \a this mesh contains some already converted elements. In this case the 2D
949  * mesh remains valid but 3D mesh becomes \b inconsistent!
950  *  \warning This method can significantly modify the order of geometric types in \a this,
951  *          hence, to write this mesh to the MED file, its cells must be sorted using
952  *          sortCellsInMEDFileFrmt().
953  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
954  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
955  *         cellIdsToConvertBg.
956  *  \throw If the coordinates array is not set.
957  *  \throw If the nodal connectivity of cells is node defined.
958  *  \throw If dimension of \a this mesh is not either 2 or 3.
959  *
960  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
961  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
962  */
963 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
964 {
965   checkFullyDefined();
966   int dim=getMeshDimension();
967   if(dim<2 || dim>3)
968     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
969   int nbOfCells=getNumberOfCells();
970   if(dim==2)
971     {
972       const int *connIndex=_nodal_connec_index->getConstPointer();
973       int *conn=_nodal_connec->getPointer();
974       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
975         {
976           if(*iter>=0 && *iter<nbOfCells)
977             {
978               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
979               if(!cm.isQuadratic())
980                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
981               else
982                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
983             }
984           else
985             {
986               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
987               oss << " in range [0," << nbOfCells << ") !";
988               throw INTERP_KERNEL::Exception(oss.str().c_str());
989             }
990         }
991     }
992   else
993     {
994       int *connIndex=_nodal_connec_index->getPointer();
995       int connIndexLgth=_nodal_connec_index->getNbOfElems();
996       const int *connOld=_nodal_connec->getConstPointer();
997       int connOldLgth=_nodal_connec->getNbOfElems();
998       std::vector<int> connNew(connOld,connOld+connOldLgth);
999       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1000         {
1001           if(*iter>=0 && *iter<nbOfCells)
1002             {
1003               int pos=connIndex[*iter];
1004               int posP1=connIndex[(*iter)+1];
1005               int lgthOld=posP1-pos-1;
1006               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1007               connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1008               unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1009               int *tmp=new int[nbOfFaces*lgthOld];
1010               int *work=tmp;
1011               for(int j=0;j<(int)nbOfFaces;j++)
1012                 {
1013                   INTERP_KERNEL::NormalizedCellType type;
1014                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1015                   work+=offset;
1016                   *work++=-1;
1017                 }
1018               std::size_t newLgth=std::distance(tmp,work)-1;
1019               std::size_t delta=newLgth-lgthOld;
1020               std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1021               connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1022               std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1023               delete [] tmp;
1024             }
1025           else
1026             {
1027               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1028               oss << " in range [0," << nbOfCells << ") !";
1029               throw INTERP_KERNEL::Exception(oss.str().c_str());
1030             }
1031         }
1032       _nodal_connec->alloc((int)connNew.size(),1);
1033       int *newConnPtr=_nodal_connec->getPointer();
1034       std::copy(connNew.begin(),connNew.end(),newConnPtr);
1035     }
1036   computeTypes();
1037 }
1038
1039 /*!
1040  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1041  * polyhedrons (if \a this is a 3D mesh).
1042  *  \warning As this method is purely for user-friendliness and no optimization is
1043  *          done to avoid construction of a useless vector, this method can be costly
1044  *          in memory.
1045  *  \throw If the coordinates array is not set.
1046  *  \throw If the nodal connectivity of cells is node defined.
1047  *  \throw If dimension of \a this mesh is not either 2 or 3.
1048  */
1049 void MEDCouplingUMesh::convertAllToPoly()
1050 {
1051   int nbOfCells=getNumberOfCells();
1052   std::vector<int> cellIds(nbOfCells);
1053   for(int i=0;i<nbOfCells;i++)
1054     cellIds[i]=i;
1055   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1056 }
1057
1058 /*!
1059  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1060  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1061  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1062  * base facet of the volume and the second half of nodes describes an opposite facet
1063  * having the same number of nodes as the base one. This method converts such
1064  * connectivity to a valid polyhedral format where connectivity of each facet is
1065  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1066  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1067  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1068  * a correct orientation of the first facet of a polyhedron, else orientation of a
1069  * corrected cell is reverse.<br>
1070  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1071  * it releases the user from boring description of polyhedra connectivity in the valid
1072  * format.
1073  *  \throw If \a this->getMeshDimension() != 3.
1074  *  \throw If \a this->getSpaceDimension() != 3.
1075  *  \throw If the nodal connectivity of cells is not defined.
1076  *  \throw If the coordinates array is not set.
1077  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1078  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1079  *
1080  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1081  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1082  */
1083 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1084 {
1085   checkFullyDefined();
1086   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1087     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1088   int nbOfCells=getNumberOfCells();
1089   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1090   newCi->alloc(nbOfCells+1,1);
1091   int *newci=newCi->getPointer();
1092   const int *ci=_nodal_connec_index->getConstPointer();
1093   const int *c=_nodal_connec->getConstPointer();
1094   newci[0]=0;
1095   for(int i=0;i<nbOfCells;i++)
1096     {
1097       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1098       if(type==INTERP_KERNEL::NORM_POLYHED)
1099         {
1100           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1101             {
1102               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1103               throw INTERP_KERNEL::Exception(oss.str().c_str());
1104             }
1105           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1106           if(n2%2!=0)
1107             {
1108               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 !";
1109               throw INTERP_KERNEL::Exception(oss.str().c_str());
1110             }
1111           int n1=(int)(n2/2);
1112           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)
1113         }
1114       else
1115         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1116     }
1117   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1118   newC->alloc(newci[nbOfCells],1);
1119   int *newc=newC->getPointer();
1120   for(int i=0;i<nbOfCells;i++)
1121     {
1122       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1123       if(type==INTERP_KERNEL::NORM_POLYHED)
1124         {
1125           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1126           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1127           *newc++=-1;
1128           for(std::size_t j=0;j<n1;j++)
1129             {
1130               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1131               newc[n1+5*j]=-1;
1132               newc[n1+5*j+1]=c[ci[i]+1+j];
1133               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1134               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1135               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1136             }
1137           newc+=n1*6;
1138         }
1139       else
1140         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1141     }
1142   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1143   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1144 }
1145
1146
1147 /*!
1148  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1149  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1150  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1151  *          to write this mesh to the MED file, its cells must be sorted using
1152  *          sortCellsInMEDFileFrmt().
1153  * \return \c true if at least one cell has been converted, \c false else. In the
1154  *         last case the nodal connectivity remains unchanged.
1155  * \throw If the coordinates array is not set.
1156  * \throw If the nodal connectivity of cells is not defined.
1157  * \throw If \a this->getMeshDimension() < 0.
1158  */
1159 bool MEDCouplingUMesh::unPolyze()
1160 {
1161   checkFullyDefined();
1162   int mdim=getMeshDimension();
1163   if(mdim<0)
1164     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1165   if(mdim<=1)
1166     return false;
1167   int nbOfCells=getNumberOfCells();
1168   if(nbOfCells<1)
1169     return false;
1170   int initMeshLgth=getMeshLength();
1171   int *conn=_nodal_connec->getPointer();
1172   int *index=_nodal_connec_index->getPointer();
1173   int posOfCurCell=0;
1174   int newPos=0;
1175   int lgthOfCurCell;
1176   bool ret=false;
1177   for(int i=0;i<nbOfCells;i++)
1178     {
1179       lgthOfCurCell=index[i+1]-posOfCurCell;
1180       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1181       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1182       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1183       int newLgth;
1184       if(cm.isDynamic())
1185         {
1186           switch(cm.getDimension())
1187             {
1188             case 2:
1189               {
1190                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1191                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1192                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1193                 break;
1194               }
1195             case 3:
1196               {
1197                 int nbOfFaces,lgthOfPolyhConn;
1198                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1199                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1200                 break;
1201               }
1202             case 1:
1203               {
1204                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1205                 break;
1206               }
1207             }
1208           ret=ret || (newType!=type);
1209           conn[newPos]=newType;
1210           newPos+=newLgth+1;
1211           posOfCurCell=index[i+1];
1212           index[i+1]=newPos;
1213         }
1214       else
1215         {
1216           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1217           newPos+=lgthOfCurCell;
1218           posOfCurCell+=lgthOfCurCell;
1219           index[i+1]=newPos;
1220         }
1221     }
1222   if(newPos!=initMeshLgth)
1223     _nodal_connec->reAlloc(newPos);
1224   if(ret)
1225     computeTypes();
1226   return ret;
1227 }
1228
1229 /*!
1230  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1231  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1232  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1233  *
1234  * \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 
1235  *             precision.
1236  */
1237 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1238 {
1239   checkFullyDefined();
1240   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1241     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1242   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1243   coords->recenterForMaxPrecision(eps);
1244   //
1245   int nbOfCells=getNumberOfCells();
1246   const int *conn=_nodal_connec->getConstPointer();
1247   const int *index=_nodal_connec_index->getConstPointer();
1248   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1249   connINew->alloc(nbOfCells+1,1);
1250   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1251   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1252   bool changed=false;
1253   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1254     {
1255       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1256         {
1257           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1258           changed=true;
1259         }
1260       else
1261         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1262       *connINewPtr=connNew->getNumberOfTuples();
1263     }
1264   if(changed)
1265     setConnectivity(connNew,connINew,false);
1266 }
1267
1268 /*!
1269  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1270  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1271  * the format of returned DataArrayInt instance.
1272  * 
1273  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1274  * \sa MEDCouplingUMesh::getNodeIdsInUse
1275  */
1276 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1277 {
1278   checkConnectivityFullyDefined();
1279   int nbOfCells=getNumberOfCells();
1280   const int *connIndex=_nodal_connec_index->getConstPointer();
1281   const int *conn=_nodal_connec->getConstPointer();
1282   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1283   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1284   std::vector<bool> retS(maxElt,false);
1285   for(int i=0;i<nbOfCells;i++)
1286     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1287       if(conn[j]>=0)
1288         retS[conn[j]]=true;
1289   int sz=0;
1290   for(int i=0;i<maxElt;i++)
1291     if(retS[i])
1292       sz++;
1293   DataArrayInt *ret=DataArrayInt::New();
1294   ret->alloc(sz,1);
1295   int *retPtr=ret->getPointer();
1296   for(int i=0;i<maxElt;i++)
1297     if(retS[i])
1298       *retPtr++=i;
1299   return ret;
1300 }
1301
1302 /*!
1303  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1304  * \sa MEDCouplingUMesh::getNodeIdsInUse
1305  */
1306 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1307 {
1308   int nbOfNodes=(int)nodeIdsInUse.size();
1309   int nbOfCells=getNumberOfCells();
1310   const int *connIndex=_nodal_connec_index->getConstPointer();
1311   const int *conn=_nodal_connec->getConstPointer();
1312   for(int i=0;i<nbOfCells;i++)
1313     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1314       if(conn[j]>=0)
1315         {
1316           if(conn[j]<nbOfNodes)
1317             nodeIdsInUse[conn[j]]=true;
1318           else
1319             {
1320               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1321               throw INTERP_KERNEL::Exception(oss.str().c_str());
1322             }
1323         }
1324 }
1325
1326 /*!
1327  * Finds nodes not used in any cell and returns an array giving a new id to every node
1328  * by excluding the unused nodes, for which the array holds -1. The result array is
1329  * a mapping in "Old to New" mode. 
1330  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1331  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1332  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1333  *          if the node is unused or a new id else. The caller is to delete this
1334  *          array using decrRef() as it is no more needed.  
1335  *  \throw If the coordinates array is not set.
1336  *  \throw If the nodal connectivity of cells is not defined.
1337  *  \throw If the nodal connectivity includes an invalid id.
1338  *
1339  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1340  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1341  * \sa computeNodeIdsAlg()
1342  */
1343 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1344 {
1345   nbrOfNodesInUse=-1;
1346   int nbOfNodes=getNumberOfNodes();
1347   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1348   ret->alloc(nbOfNodes,1);
1349   int *traducer=ret->getPointer();
1350   std::fill(traducer,traducer+nbOfNodes,-1);
1351   int nbOfCells=getNumberOfCells();
1352   const int *connIndex=_nodal_connec_index->getConstPointer();
1353   const int *conn=_nodal_connec->getConstPointer();
1354   for(int i=0;i<nbOfCells;i++)
1355     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1356       if(conn[j]>=0)
1357         {
1358           if(conn[j]<nbOfNodes)
1359             traducer[conn[j]]=1;
1360           else
1361             {
1362               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1363               throw INTERP_KERNEL::Exception(oss.str().c_str());
1364             }
1365         }
1366   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1367   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1368   return ret.retn();
1369 }
1370
1371 /*!
1372  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1373  * For each cell in \b this the number of nodes constituting cell is computed.
1374  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1375  * So for pohyhedrons some nodes can be counted several times in the returned result.
1376  * 
1377  * \return a newly allocated array
1378  */
1379 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1380 {
1381   checkConnectivityFullyDefined();
1382   int nbOfCells=getNumberOfCells();
1383   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1384   ret->alloc(nbOfCells,1);
1385   int *retPtr=ret->getPointer();
1386   const int *conn=getNodalConnectivity()->getConstPointer();
1387   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1388   for(int i=0;i<nbOfCells;i++,retPtr++)
1389     {
1390       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1391         *retPtr=connI[i+1]-connI[i]-1;
1392       else
1393         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1394     }
1395   return ret.retn();
1396 }
1397
1398 /*!
1399  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1400  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1401  * 
1402  * \return a newly allocated array
1403  */
1404 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
1405 {
1406   checkConnectivityFullyDefined();
1407   int nbOfCells=getNumberOfCells();
1408   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1409   ret->alloc(nbOfCells,1);
1410   int *retPtr=ret->getPointer();
1411   const int *conn=getNodalConnectivity()->getConstPointer();
1412   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1413   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1414     {
1415       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1416       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1417     }
1418   return ret.retn();
1419 }
1420
1421 /*!
1422  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1423  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1424  * array mean that the corresponding old node is no more used. 
1425  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1426  *           this->getNumberOfNodes() before call of this method. The caller is to
1427  *           delete this array using decrRef() as it is no more needed. 
1428  *  \throw If the coordinates array is not set.
1429  *  \throw If the nodal connectivity of cells is not defined.
1430  *  \throw If the nodal connectivity includes an invalid id.
1431  *
1432  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1433  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1434  */
1435 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1436 {
1437   return MEDCouplingPointSet::zipCoordsTraducer();
1438 }
1439
1440 /*!
1441  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1442  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1443  */
1444 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1445 {
1446   switch(compType)
1447     {
1448     case 0:
1449       return AreCellsEqual0(conn,connI,cell1,cell2);
1450     case 1:
1451       return AreCellsEqual1(conn,connI,cell1,cell2);
1452     case 2:
1453       return AreCellsEqual2(conn,connI,cell1,cell2);
1454     case 3:
1455       return AreCellsEqual3(conn,connI,cell1,cell2);
1456     case 7:
1457       return AreCellsEqual7(conn,connI,cell1,cell2);
1458     }
1459   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1460 }
1461
1462 /*!
1463  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1464  */
1465 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1466 {
1467   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1468     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1469   return 0;
1470 }
1471
1472 /*!
1473  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1474  */
1475 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1476 {
1477   int sz=connI[cell1+1]-connI[cell1];
1478   if(sz==connI[cell2+1]-connI[cell2])
1479     {
1480       if(conn[connI[cell1]]==conn[connI[cell2]])
1481         {
1482           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1483           unsigned dim=cm.getDimension();
1484           if(dim!=3)
1485             {
1486               if(dim!=1)
1487                 {
1488                   int sz1=2*(sz-1);
1489                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1490                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1491                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1492                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1493                   return work!=tmp+sz1?1:0;
1494                 }
1495               else
1496                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1497             }
1498           else
1499             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1500         }
1501     }
1502   return 0;
1503 }
1504
1505 /*!
1506  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1507  */
1508 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1509 {
1510   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1511     {
1512       if(conn[connI[cell1]]==conn[connI[cell2]])
1513         {
1514           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1515           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1516           return s1==s2?1:0;
1517         }
1518     }
1519   return 0;
1520 }
1521
1522 /*!
1523  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1524  */
1525 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1526 {
1527   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1528     {
1529       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1530       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1531       return s1==s2?1:0;
1532     }
1533   return 0;
1534 }
1535
1536 /*!
1537  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1538  */
1539 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1540 {
1541   int sz=connI[cell1+1]-connI[cell1];
1542   if(sz==connI[cell2+1]-connI[cell2])
1543     {
1544       if(conn[connI[cell1]]==conn[connI[cell2]])
1545         {
1546           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1547           unsigned dim=cm.getDimension();
1548           if(dim!=3)
1549             {
1550               if(dim!=1)
1551                 {
1552                   int sz1=2*(sz-1);
1553                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1554                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1555                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1556                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1557                   if(work!=tmp+sz1)
1558                     return 1;
1559                   else
1560                     {
1561                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1562                       std::reverse_iterator<int *> it2((int *)tmp);
1563                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1564                         return 2;
1565                       else
1566                         return 0;
1567                     }
1568                   
1569                   return work!=tmp+sz1?1:0;
1570                 }
1571               else
1572                 {//case of SEG2 and SEG3
1573                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1574                     return 1;
1575                   if(!cm.isQuadratic())
1576                     {
1577                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1578                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1579                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1580                         return 2;
1581                       return 0;
1582                     }
1583                   else
1584                     {
1585                       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])
1586                         return 2;
1587                       return 0;
1588                     }
1589                 }
1590             }
1591           else
1592             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1593         }
1594     }
1595   return 0;
1596 }
1597
1598 /*!
1599  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1600  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1601  * and result remains unchanged.
1602  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1603  * If in 'candidates' pool -1 value is considered as an empty value.
1604  * WARNING this method returns only ONE set of result !
1605  */
1606 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1607 {
1608   if(candidates.size()<1)
1609     return false;
1610   bool ret=false;
1611   std::vector<int>::const_iterator iter=candidates.begin();
1612   int start=(*iter++);
1613   for(;iter!=candidates.end();iter++)
1614     {
1615       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1616       if(status!=0)
1617         {
1618           if(!ret)
1619             {
1620               result->pushBackSilent(start);
1621               ret=true;
1622             }
1623           if(status==1)
1624             result->pushBackSilent(*iter);
1625           else
1626             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1627         }
1628     }
1629   return ret;
1630 }
1631
1632 /*!
1633  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1634  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1635  *
1636  * \param [in] compType input specifying the technique used to compare cells each other.
1637  *   - 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.
1638  *   - 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)
1639  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1640  *   - 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
1641  * can be used for users not sensitive to orientation of cell
1642  * \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.
1643  * \param [out] commonCells
1644  * \param [out] commonCellsI
1645  * \return the correspondance array old to new in a newly allocated array.
1646  * 
1647  */
1648 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1649 {
1650   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1651   getReverseNodalConnectivity(revNodal,revNodalI);
1652   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1653 }
1654
1655 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1656                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1657 {
1658   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1659   int nbOfCells=nodalI->getNumberOfTuples()-1;
1660   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1661   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1662   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1663   std::vector<bool> isFetched(nbOfCells,false);
1664   if(startCellId==0)
1665     {
1666       for(int i=0;i<nbOfCells;i++)
1667         {
1668           if(!isFetched[i])
1669             {
1670               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1671               std::vector<int> v,v2;
1672               if(connOfNode!=connPtr+connIPtr[i+1])
1673                 {
1674                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1675                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1676                   connOfNode++;
1677                 }
1678               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1679                 if(*connOfNode>=0)
1680                   {
1681                     v=v2;
1682                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1683                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1684                     v2.resize(std::distance(v2.begin(),it));
1685                   }
1686               if(v2.size()>1)
1687                 {
1688                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1689                     {
1690                       int pos=commonCellsI->back();
1691                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1692                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1693                         isFetched[*it]=true;
1694                     }
1695                 }
1696             }
1697         }
1698     }
1699   else
1700     {
1701       for(int i=startCellId;i<nbOfCells;i++)
1702         {
1703           if(!isFetched[i])
1704             {
1705               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1706               std::vector<int> v,v2;
1707               if(connOfNode!=connPtr+connIPtr[i+1])
1708                 {
1709                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1710                   connOfNode++;
1711                 }
1712               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1713                 if(*connOfNode>=0)
1714                   {
1715                     v=v2;
1716                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1717                     v2.resize(std::distance(v2.begin(),it));
1718                   }
1719               if(v2.size()>1)
1720                 {
1721                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1722                     {
1723                       int pos=commonCellsI->back();
1724                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1725                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1726                         isFetched[*it]=true;
1727                     }
1728                 }
1729             }
1730         }
1731     }
1732   commonCellsArr=commonCells.retn();
1733   commonCellsIArr=commonCellsI.retn();
1734 }
1735
1736 /*!
1737  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1738  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1739  * than \a other->getNumberOfCells() in the returned array means that there is no
1740  * corresponding cell in \a this mesh.
1741  * It is expected that \a this and \a other meshes share the same node coordinates
1742  * array, if it is not so an exception is thrown. 
1743  *  \param [in] other - the mesh to compare with.
1744  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1745  *         valid values [0,1,2], see zipConnectivityTraducer().
1746  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1747  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1748  *         values. The caller is to delete this array using
1749  *         decrRef() as it is no more needed.
1750  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1751  *         mesh.
1752  *
1753  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1754  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1755  *  \sa checkDeepEquivalOnSameNodesWith()
1756  *  \sa checkGeoEquivalWith()
1757  */
1758 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1759 {
1760   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1761   int nbOfCells=getNumberOfCells();
1762   static const int possibleCompType[]={0,1,2};
1763   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1764     {
1765       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1766       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1767       oss << " !";
1768       throw INTERP_KERNEL::Exception(oss.str().c_str());
1769     }
1770   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1771   arr=o2n->substr(nbOfCells);
1772   arr->setName(other->getName());
1773   int tmp;
1774   if(other->getNumberOfCells()==0)
1775     return true;
1776   return arr->getMaxValue(tmp)<nbOfCells;
1777 }
1778
1779 /*!
1780  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1781  * This method tries to determine if \b other is fully included in \b this.
1782  * The main difference is that this method is not expected to throw exception.
1783  * This method has two outputs :
1784  *
1785  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1786  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1787  */
1788 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1789 {
1790   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1791   DataArrayInt *commonCells=0,*commonCellsI=0;
1792   int thisNbCells=getNumberOfCells();
1793   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1794   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1795   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1796   int otherNbCells=other->getNumberOfCells();
1797   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1798   arr2->alloc(otherNbCells,1);
1799   arr2->fillWithZero();
1800   int *arr2Ptr=arr2->getPointer();
1801   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1802   for(int i=0;i<nbOfCommon;i++)
1803     {
1804       int start=commonCellsPtr[commonCellsIPtr[i]];
1805       if(start<thisNbCells)
1806         {
1807           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1808             {
1809               int sig=commonCellsPtr[j]>0?1:-1;
1810               int val=std::abs(commonCellsPtr[j])-1;
1811               if(val>=thisNbCells)
1812                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1813             }
1814         }
1815     }
1816   arr2->setName(other->getName());
1817   if(arr2->presenceOfValue(0))
1818     return false;
1819   arr=arr2.retn();
1820   return true;
1821 }
1822
1823 /*!
1824  * Merges nodes equal within \a precision and returns an array describing the 
1825  * permutation used to remove duplicate nodes.
1826  *  \param [in] precision - minimal absolute distance between two nodes at which they are
1827  *              considered not coincident.
1828  *  \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1829  *  \param [out] newNbOfNodes - number of nodes remaining after the removal.
1830  *  \return DataArrayInt * - the permutation array in "Old to New" mode. For more 
1831  *          info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1832  *          is to delete this array using decrRef() as it is no more needed.
1833  *  \throw If the coordinates array is not set.
1834  *  \throw If the nodal connectivity of cells is not defined.
1835  *
1836  *  \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1837  *  \ref  py_mcumesh_mergeNodes "Here is a Python example".
1838  */
1839 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1840 {
1841   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1842   if(areNodesMerged)
1843     renumberNodes(ret->begin(),newNbOfNodes);
1844   return ret.retn();
1845 }
1846
1847
1848 /*!
1849  * Merges nodes equal within \a precision and returns an array describing the 
1850  * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
1851  *  of merged nodes is changed to be at their barycenter.
1852  *  \param [in] precision - minimal absolute distance between two nodes at which they are
1853  *              considered not coincident.
1854  *  \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1855  *  \param [out] newNbOfNodes - number of nodes remaining after the removal.
1856  *  \return DataArrayInt * - the permutation array in "Old to New" mode. For more 
1857  *          info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1858  *          is to delete this array using decrRef() as it is no more needed.
1859  *  \throw If the coordinates array is not set.
1860  *  \throw If the nodal connectivity of cells is not defined.
1861  *
1862  *  \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1863  *  \ref  py_mcumesh_mergeNodes "Here is a Python example".
1864  */
1865 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
1866 {
1867   DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1868   if(areNodesMerged)
1869     renumberNodes2(ret->getConstPointer(),newNbOfNodes);
1870   return ret;
1871 }
1872
1873 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1874 {
1875   if(!other)
1876     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1877   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1878   if(!otherC)
1879     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1880   std::vector<const MEDCouplingUMesh *> ms(2);
1881   ms[0]=this;
1882   ms[1]=otherC;
1883   return MergeUMeshesOnSameCoords(ms);
1884 }
1885
1886 /*!
1887  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1888  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1889  * cellIds is not given explicitely but by a range python like.
1890  * 
1891  * \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.
1892  * \return a newly allocated
1893  * 
1894  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1895  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1896  */
1897 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1898 {
1899   if(getMeshDimension()!=-1)
1900     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1901   else
1902     {
1903       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1904       if(newNbOfCells!=1)
1905         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1906       if(start!=0)
1907         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1908       incrRef();
1909       return const_cast<MEDCouplingUMesh *>(this);
1910     }
1911 }
1912
1913 /*!
1914  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1915  * The result mesh shares or not the node coordinates array with \a this mesh depending
1916  * on \a keepCoords parameter.
1917  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1918  *           to write this mesh to the MED file, its cells must be sorted using
1919  *           sortCellsInMEDFileFrmt().
1920  *  \param [in] begin - an array of cell ids to include to the new mesh.
1921  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1922  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1923  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1924  *         by calling zipCoords().
1925  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1926  *         to delete this mesh using decrRef() as it is no more needed. 
1927  *  \throw If the coordinates array is not set.
1928  *  \throw If the nodal connectivity of cells is not defined.
1929  *  \throw If any cell id in the array \a begin is not valid.
1930  *
1931  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1932  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1933  */
1934 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1935 {
1936   if(getMeshDimension()!=-1)
1937     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1938   else
1939     {
1940       if(end-begin!=1)
1941         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1942       if(begin[0]!=0)
1943         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1944       incrRef();
1945       return const_cast<MEDCouplingUMesh *>(this);
1946     }
1947 }
1948
1949 /*!
1950  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1951  *
1952  * 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.
1953  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1954  * The number of cells of \b this will remain the same with this method.
1955  *
1956  * \param [in] begin begin of cell ids (included) of cells in this to assign
1957  * \param [in] end end of cell ids (excluded) of cells in this to assign
1958  * \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 ).
1959  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1960  */
1961 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1962 {
1963   checkConnectivityFullyDefined();
1964   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1965   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1966     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1967   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1968     {
1969       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1970       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1971       throw INTERP_KERNEL::Exception(oss.str().c_str());
1972     }
1973   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1974   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1975     {
1976       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1977       throw INTERP_KERNEL::Exception(oss.str().c_str());
1978     }
1979   int nbOfCells=getNumberOfCells();
1980   bool easyAssign=true;
1981   const int *connI=_nodal_connec_index->getConstPointer();
1982   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1983   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1984     {
1985       if(*it>=0 && *it<nbOfCells)
1986         {
1987           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1988         }
1989       else
1990         {
1991           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1992           throw INTERP_KERNEL::Exception(oss.str().c_str());
1993         }
1994     }
1995   if(easyAssign)
1996     {
1997       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1998       computeTypes();
1999     }
2000   else
2001     {
2002       DataArrayInt *arrOut=0,*arrIOut=0;
2003       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2004                                                arrOut,arrIOut);
2005       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2006       setConnectivity(arrOut,arrIOut,true);
2007     }
2008 }
2009
2010 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2011 {
2012   checkConnectivityFullyDefined();
2013   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2014   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2015     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2016   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2017     {
2018       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2019       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2020       throw INTERP_KERNEL::Exception(oss.str().c_str());
2021     }
2022   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2023   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2024     {
2025       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2026       throw INTERP_KERNEL::Exception(oss.str().c_str());
2027     }
2028   int nbOfCells=getNumberOfCells();
2029   bool easyAssign=true;
2030   const int *connI=_nodal_connec_index->getConstPointer();
2031   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2032   int it=start;
2033   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2034     {
2035       if(it>=0 && it<nbOfCells)
2036         {
2037           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2038         }
2039       else
2040         {
2041           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2042           throw INTERP_KERNEL::Exception(oss.str().c_str());
2043         }
2044     }
2045   if(easyAssign)
2046     {
2047       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2048       computeTypes();
2049     }
2050   else
2051     {
2052       DataArrayInt *arrOut=0,*arrIOut=0;
2053       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2054                                                 arrOut,arrIOut);
2055       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2056       setConnectivity(arrOut,arrIOut,true);
2057     }
2058 }                      
2059
2060 /*!
2061  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2062  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2063  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2064  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2065  *
2066  * \param [in] begin input start of array of node ids.
2067  * \param [in] end input end of array of node ids.
2068  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2069  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2070  */
2071 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2072 {
2073   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2074   checkConnectivityFullyDefined();
2075   int tmp=-1;
2076   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2077   std::vector<bool> fastFinder(sz,false);
2078   for(const int *work=begin;work!=end;work++)
2079     if(*work>=0 && *work<sz)
2080       fastFinder[*work]=true;
2081   int nbOfCells=getNumberOfCells();
2082   const int *conn=getNodalConnectivity()->getConstPointer();
2083   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2084   for(int i=0;i<nbOfCells;i++)
2085     {
2086       int ref=0,nbOfHit=0;
2087       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2088         if(*work2>=0)
2089           {
2090             ref++;
2091             if(fastFinder[*work2])
2092               nbOfHit++;
2093           }
2094       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2095         cellIdsKept->pushBackSilent(i);
2096     }
2097   cellIdsKeptArr=cellIdsKept.retn();
2098 }
2099
2100 /*!
2101  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2102  * this->getMeshDimension(), that bound some cells of \a this mesh.
2103  * The cells of lower dimension to include to the result mesh are selected basing on
2104  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2105  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2106  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2107  * created mesh shares the node coordinates array with \a this mesh. 
2108  *  \param [in] begin - the array of node ids.
2109  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2110  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2111  *         array \a begin are added, else cells whose any node is in the
2112  *         array \a begin are added.
2113  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2114  *         to delete this mesh using decrRef() as it is no more needed. 
2115  *  \throw If the coordinates array is not set.
2116  *  \throw If the nodal connectivity of cells is not defined.
2117  *  \throw If any node id in \a begin is not valid.
2118  *
2119  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2120  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2121  */
2122 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2123 {
2124   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2125   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2126   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2127   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2128   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2129 }
2130
2131 /*!
2132  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2133  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2134  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2135  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2136  *         by calling zipCoords().
2137  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2138  *         to delete this mesh using decrRef() as it is no more needed. 
2139  *  \throw If the coordinates array is not set.
2140  *  \throw If the nodal connectivity of cells is not defined.
2141  *
2142  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2143  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2144  */
2145 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2146 {
2147   DataArrayInt *desc=DataArrayInt::New();
2148   DataArrayInt *descIndx=DataArrayInt::New();
2149   DataArrayInt *revDesc=DataArrayInt::New();
2150   DataArrayInt *revDescIndx=DataArrayInt::New();
2151   //
2152   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2153   revDesc->decrRef();
2154   desc->decrRef();
2155   descIndx->decrRef();
2156   int nbOfCells=meshDM1->getNumberOfCells();
2157   const int *revDescIndxC=revDescIndx->getConstPointer();
2158   std::vector<int> boundaryCells;
2159   for(int i=0;i<nbOfCells;i++)
2160     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2161       boundaryCells.push_back(i);
2162   revDescIndx->decrRef();
2163   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2164   return ret;
2165 }
2166
2167 /*!
2168  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2169  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2170  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2171  */
2172 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2173 {
2174   checkFullyDefined();
2175   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2176   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2177   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2178   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2179   //
2180   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2181   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2182   //
2183   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2184   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2185   const int *revDescPtr=revDesc->getConstPointer();
2186   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2187   int nbOfCells=getNumberOfCells();
2188   std::vector<bool> ret1(nbOfCells,false);
2189   int sz=0;
2190   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2191     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2192       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2193   //
2194   DataArrayInt *ret2=DataArrayInt::New();
2195   ret2->alloc(sz,1);
2196   int *ret2Ptr=ret2->getPointer();
2197   sz=0;
2198   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2199     if(*it)
2200       *ret2Ptr++=sz;
2201   ret2->setName("BoundaryCells");
2202   return ret2;
2203 }
2204
2205 /*!
2206  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2207  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2208  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2209  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2210  *
2211  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2212  * This method method returns cells ids set s = s1 + s2 where :
2213  * 
2214  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2215  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2216  *
2217  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2218  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2219  *
2220  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2221  * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2222  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2223  */
2224 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2225 {
2226   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2227     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2228   checkConnectivityFullyDefined();
2229   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2230   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2231     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2232   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2233   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2234   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2235   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2236   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2237   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2238   DataArrayInt *idsOtherInConsti=0;
2239   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2240   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2241   if(!b)
2242     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2243   std::set<int> s1;
2244   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2245     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2246   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2247   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2248   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2249   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2250   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2251   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2252   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2253   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2254   neighThisPartAuto=0;
2255   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2256   const int li[2]={0,1};
2257   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2258   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2259   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2260   s_renum1->sort();
2261   //
2262   cellIdsRk0=s0arr.retn();
2263   cellIdsRk1=s_renum1.retn();
2264 }
2265
2266 /*!
2267  * 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
2268  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2269  * 
2270  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2271  */
2272 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2273 {
2274   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2275   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2276   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2278   //
2279   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2280   revDesc=0; desc=0; descIndx=0;
2281   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2282   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2283   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2284 }
2285
2286 /*!
2287  * Finds nodes lying on the boundary of \a this mesh.
2288  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2289  *          nodes. The caller is to delete this array using decrRef() as it is no
2290  *          more needed.
2291  *  \throw If the coordinates array is not set.
2292  *  \throw If the nodal connectivity of cells is node defined.
2293  *
2294  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2295  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2296  */
2297 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2298 {
2299   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2300   return skin->computeFetchedNodeIds();
2301 }
2302
2303 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2304 {
2305   incrRef();
2306   return const_cast<MEDCouplingUMesh *>(this);
2307 }
2308
2309 /*!
2310  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2311  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2312  * 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.
2313  * 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.
2314  * 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.
2315  *
2316  * \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
2317  *             parameter is altered during the call.
2318  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2319  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2320  * \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.
2321  *
2322  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2323  */
2324 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2325                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2326 {
2327   checkFullyDefined();
2328   otherDimM1OnSameCoords.checkFullyDefined();
2329   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2330     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2331   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2332     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2333   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2334   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2337   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2338   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2339   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2340   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2341   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2342   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2343   //
2344   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2345   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2346   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2347   DataArrayInt *idsTmp=0;
2348   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2349   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2350   if(!b)
2351     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2352   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2353   DataArrayInt *tmp0=0,*tmp1=0;
2354   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2355   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2356   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2357   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2358   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2359   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2360   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2361   //
2362   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2363   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2364   nodeIdsToDuplicate=s3.retn();
2365 }
2366
2367 /*!
2368  * This method operates a modification of the connectivity and coords in \b this.
2369  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2370  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2371  * 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
2372  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2373  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2374  * 
2375  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2376  * 
2377  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2378  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2379  */
2380 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2381 {
2382   int nbOfNodes=getNumberOfNodes();
2383   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2384   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2385 }
2386
2387 /*!
2388  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2389  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2390  * This method is a generalization of shiftNodeNumbersInConn().
2391  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2392  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2393  *         this->getNumberOfNodes(), in "Old to New" mode. 
2394  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2395  *  \throw If the nodal connectivity of cells is not defined.
2396  *
2397  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2398  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2399  */
2400 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2401 {
2402   checkConnectivityFullyDefined();
2403   int *conn=getNodalConnectivity()->getPointer();
2404   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2405   int nbOfCells=getNumberOfCells();
2406   for(int i=0;i<nbOfCells;i++)
2407     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2408       {
2409         int& node=conn[iconn];
2410         if(node>=0)//avoid polyhedron separator
2411           {
2412             node=newNodeNumbersO2N[node];
2413           }
2414       }
2415   _nodal_connec->declareAsNew();
2416   updateTime();
2417 }
2418
2419 /*!
2420  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2421  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2422  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2423  * 
2424  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2425  */
2426 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2427 {
2428   checkConnectivityFullyDefined();
2429   int *conn=getNodalConnectivity()->getPointer();
2430   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2431   int nbOfCells=getNumberOfCells();
2432   for(int i=0;i<nbOfCells;i++)
2433     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2434       {
2435         int& node=conn[iconn];
2436         if(node>=0)//avoid polyhedron separator
2437           {
2438             node+=delta;
2439           }
2440       }
2441   _nodal_connec->declareAsNew();
2442   updateTime();
2443 }
2444
2445 /*!
2446  * This method operates a modification of the connectivity in \b this.
2447  * 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.
2448  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2449  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2450  * 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
2451  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2452  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2453  * 
2454  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2455  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2456  * 
2457  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2458  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2459  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2460  */
2461 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2462 {
2463   checkConnectivityFullyDefined();
2464   std::map<int,int> m;
2465   int val=offset;
2466   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2467     m[*work]=val;
2468   int *conn=getNodalConnectivity()->getPointer();
2469   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2470   int nbOfCells=getNumberOfCells();
2471   for(int i=0;i<nbOfCells;i++)
2472     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2473       {
2474         int& node=conn[iconn];
2475         if(node>=0)//avoid polyhedron separator
2476           {
2477             std::map<int,int>::iterator it=m.find(node);
2478             if(it!=m.end())
2479               node=(*it).second;
2480           }
2481       }
2482   updateTime();
2483 }
2484
2485 /*!
2486  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2487  *
2488  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2489  * After the call of this method the number of cells remains the same as before.
2490  *
2491  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2492  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2493  * be strictly in [0;this->getNumberOfCells()).
2494  *
2495  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2496  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2497  * should be contained in[0;this->getNumberOfCells()).
2498  * 
2499  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2500  */
2501 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2502 {
2503   checkConnectivityFullyDefined();
2504   int nbCells=getNumberOfCells();
2505   const int *array=old2NewBg;
2506   if(check)
2507     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2508   //
2509   const int *conn=_nodal_connec->getConstPointer();
2510   const int *connI=_nodal_connec_index->getConstPointer();
2511   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2512   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2513   const int *n2oPtr=n2o->begin();
2514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2515   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2516   newConn->copyStringInfoFrom(*_nodal_connec);
2517   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2518   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2519   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2520   //
2521   int *newC=newConn->getPointer();
2522   int *newCI=newConnI->getPointer();
2523   int loc=0;
2524   newCI[0]=loc;
2525   for(int i=0;i<nbCells;i++)
2526     {
2527       int pos=n2oPtr[i];
2528       int nbOfElts=connI[pos+1]-connI[pos];
2529       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2530       loc+=nbOfElts;
2531       newCI[i+1]=loc;
2532     }
2533   //
2534   setConnectivity(newConn,newConnI);
2535   if(check)
2536     free(const_cast<int *>(array));
2537 }
2538
2539 /*!
2540  * Finds cells whose bounding boxes intersect a given bounding box.
2541  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2542  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2543  *         zMax (if in 3D). 
2544  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2545  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2546  *         extent of the bounding box of cell to produce an addition to this bounding box.
2547  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2548  *         cells. The caller is to delete this array using decrRef() as it is no more
2549  *         needed. 
2550  *  \throw If the coordinates array is not set.
2551  *  \throw If the nodal connectivity of cells is not defined.
2552  *
2553  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2554  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2555  */
2556 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2557 {
2558   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2559   if(getMeshDimension()==-1)
2560     {
2561       elems->pushBackSilent(0);
2562       return elems.retn();
2563     }
2564   int dim=getSpaceDimension();
2565   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2566   const int* conn      = getNodalConnectivity()->getConstPointer();
2567   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2568   const double* coords = getCoords()->getConstPointer();
2569   int nbOfCells=getNumberOfCells();
2570   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2571     {
2572       for (int i=0; i<dim; i++)
2573         {
2574           elem_bb[i*2]=std::numeric_limits<double>::max();
2575           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2576         }
2577
2578       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2579         {
2580           int node= conn[inode];
2581           if(node>=0)//avoid polyhedron separator
2582             {
2583               for (int idim=0; idim<dim; idim++)
2584                 {
2585                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2586                     {
2587                       elem_bb[idim*2] = coords[node*dim+idim] ;
2588                     }
2589                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2590                     {
2591                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2592                     }
2593                 }
2594             }
2595         }
2596       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2597         elems->pushBackSilent(ielem);
2598     }
2599   return elems.retn();
2600 }
2601
2602 /*!
2603  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2604  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2605  * added in 'elems' parameter.
2606  */
2607 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2608 {
2609   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2610   if(getMeshDimension()==-1)
2611     {
2612       elems->pushBackSilent(0);
2613       return elems.retn();
2614     }
2615   int dim=getSpaceDimension();
2616   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2617   const int* conn      = getNodalConnectivity()->getConstPointer();
2618   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2619   const double* coords = getCoords()->getConstPointer();
2620   int nbOfCells=getNumberOfCells();
2621   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2622     {
2623       for (int i=0; i<dim; i++)
2624         {
2625           elem_bb[i*2]=std::numeric_limits<double>::max();
2626           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2627         }
2628
2629       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2630         {
2631           int node= conn[inode];
2632           if(node>=0)//avoid polyhedron separator
2633             {
2634               for (int idim=0; idim<dim; idim++)
2635                 {
2636                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2637                     {
2638                       elem_bb[idim*2] = coords[node*dim+idim] ;
2639                     }
2640                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2641                     {
2642                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2643                     }
2644                 }
2645             }
2646         }
2647       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2648         elems->pushBackSilent(ielem);
2649     }
2650   return elems.retn();
2651 }
2652
2653 /*!
2654  * Returns a type of a cell by its id.
2655  *  \param [in] cellId - the id of the cell of interest.
2656  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2657  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2658  */
2659 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2660 {
2661   const int *ptI=_nodal_connec_index->getConstPointer();
2662   const int *pt=_nodal_connec->getConstPointer();
2663   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2664     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2665   else
2666     {
2667       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2668       throw INTERP_KERNEL::Exception(oss.str().c_str());
2669     }
2670 }
2671
2672 /*!
2673  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2674  * This method does not throw exception if geometric type \a type is not in \a this.
2675  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2676  * The coordinates array is not considered here.
2677  *
2678  * \param [in] type the geometric type
2679  * \return cell ids in this having geometric type \a type.
2680  */
2681 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2682 {
2683   
2684   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2685   ret->alloc(0,1);
2686   checkConnectivityFullyDefined();
2687   int nbCells=getNumberOfCells();
2688   int mdim=getMeshDimension();
2689   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2690   if(mdim!=(int)cm.getDimension())
2691     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2692   const int *ptI=_nodal_connec_index->getConstPointer();
2693   const int *pt=_nodal_connec->getConstPointer();
2694   for(int i=0;i<nbCells;i++)
2695     {
2696       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2697         ret->pushBackSilent(i);
2698     }
2699   return ret.retn();
2700 }
2701
2702 /*!
2703  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2704  */
2705 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2706 {
2707   const int *ptI=_nodal_connec_index->getConstPointer();
2708   const int *pt=_nodal_connec->getConstPointer();
2709   int nbOfCells=getNumberOfCells();
2710   int ret=0;
2711   for(int i=0;i<nbOfCells;i++)
2712     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2713       ret++;
2714   return ret;
2715 }
2716
2717 /*!
2718  * Returns the nodal connectivity of a given cell.
2719  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2720  * all returned node ids can be used in getCoordinatesOfNode().
2721  *  \param [in] cellId - an id of the cell of interest.
2722  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2723  *         cleared before the appending.
2724  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2725  */
2726 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2727 {
2728   const int *ptI=_nodal_connec_index->getConstPointer();
2729   const int *pt=_nodal_connec->getConstPointer();
2730   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2731     if(*w>=0)
2732       conn.push_back(*w);
2733 }
2734
2735 std::string MEDCouplingUMesh::simpleRepr() const
2736 {
2737   static const char msg0[]="No coordinates specified !";
2738   std::ostringstream ret;
2739   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2740   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2741   int tmpp1,tmpp2;
2742   double tt=getTime(tmpp1,tmpp2);
2743   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2744   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2745   if(_mesh_dim>=-1)
2746     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2747   else
2748     { ret << " Mesh dimension has not been set or is invalid !"; }
2749   if(_coords!=0)
2750     {
2751       const int spaceDim=getSpaceDimension();
2752       ret << spaceDim << "\nInfo attached on space dimension : ";
2753       for(int i=0;i<spaceDim;i++)
2754         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2755       ret << "\n";
2756     }
2757   else
2758     ret << msg0 << "\n";
2759   ret << "Number of nodes : ";
2760   if(_coords!=0)
2761     ret << getNumberOfNodes() << "\n";
2762   else
2763     ret << msg0 << "\n";
2764   ret << "Number of cells : ";
2765   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2766     ret << getNumberOfCells() << "\n";
2767   else
2768     ret << "No connectivity specified !" << "\n";
2769   ret << "Cell types present : ";
2770   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2771     {
2772       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2773       ret << cm.getRepr() << " ";
2774     }
2775   ret << "\n";
2776   return ret.str();
2777 }
2778
2779 std::string MEDCouplingUMesh::advancedRepr() const
2780 {
2781   std::ostringstream ret;
2782   ret << simpleRepr();
2783   ret << "\nCoordinates array : \n___________________\n\n";
2784   if(_coords)
2785     _coords->reprWithoutNameStream(ret);
2786   else
2787     ret << "No array set !\n";
2788   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2789   reprConnectivityOfThisLL(ret);
2790   return ret.str();
2791 }
2792
2793 /*!
2794  * This method returns a C++ code that is a dump of \a this.
2795  * This method will throw if this is not fully defined.
2796  */
2797 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2798 {
2799   static const char coordsName[]="coords";
2800   static const char connName[]="conn";
2801   static const char connIName[]="connI";
2802   checkFullyDefined();
2803   std::ostringstream ret; ret << "// coordinates" << std::endl;
2804   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2805   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2806   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2807   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2808   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2809   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2810   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2811   return ret.str();
2812 }
2813
2814 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2815 {
2816   std::ostringstream ret;
2817   reprConnectivityOfThisLL(ret);
2818   return ret.str();
2819 }
2820
2821 /*!
2822  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2823  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2824  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2825  * some algos).
2826  * 
2827  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2828  * 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
2829  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2830  */
2831 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2832 {
2833   int mdim=getMeshDimension();
2834   if(mdim<0)
2835     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2836   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2837   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2838   bool needToCpyCT=true;
2839   if(!_nodal_connec)
2840     {
2841       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2842       needToCpyCT=false;
2843     }
2844   else
2845     {
2846       tmp1=_nodal_connec;
2847       tmp1->incrRef();
2848     }
2849   if(!_nodal_connec_index)
2850     {
2851       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2852       needToCpyCT=false;
2853     }
2854   else
2855     {
2856       tmp2=_nodal_connec_index;
2857       tmp2->incrRef();
2858     }
2859   ret->setConnectivity(tmp1,tmp2,false);
2860   if(needToCpyCT)
2861     ret->_types=_types;
2862   if(!_coords)
2863     {
2864       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2865       ret->setCoords(coords);
2866     }
2867   else
2868     ret->setCoords(_coords);
2869   return ret.retn();
2870 }
2871
2872 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2873 {
2874   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2875     {
2876       int nbOfCells=getNumberOfCells();
2877       const int *c=_nodal_connec->getConstPointer();
2878       const int *ci=_nodal_connec_index->getConstPointer();
2879       for(int i=0;i<nbOfCells;i++)
2880         {
2881           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2882           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2883           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2884           stream << "\n";
2885         }
2886     }
2887   else
2888     stream << "Connectivity not defined !\n";
2889 }
2890
2891 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2892 {
2893   const int *ptI=_nodal_connec_index->getConstPointer();
2894   const int *pt=_nodal_connec->getConstPointer();
2895   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2896     return ptI[cellId+1]-ptI[cellId]-1;
2897   else
2898     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2899 }
2900
2901 /*!
2902  * Returns types of cells of the specified part of \a this mesh.
2903  * This method avoids computing sub-mesh explicitely to get its types.
2904  *  \param [in] begin - an array of cell ids of interest.
2905  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2906  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2907  *         describing the cell types. 
2908  *  \throw If the coordinates array is not set.
2909  *  \throw If the nodal connectivity of cells is not defined.
2910  *  \sa getAllTypes()
2911  */
2912 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2913 {
2914   checkFullyDefined();
2915   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2916   const int *conn=_nodal_connec->getConstPointer();
2917   const int *connIndex=_nodal_connec_index->getConstPointer();
2918   for(const int *w=begin;w!=end;w++)
2919     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2920   return ret;
2921 }
2922
2923 /*!
2924  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2925  * a set of types of cells constituting \a this mesh. 
2926  * This method is for advanced users having prepared their connectivity before. For
2927  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2928  *  \param [in] conn - the nodal connectivity array. 
2929  *  \param [in] connIndex - the nodal connectivity index array.
2930  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2931  *         mesh is updated.
2932  */
2933 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2934 {
2935   DataArrayInt::SetArrayIn(conn,_nodal_connec);
2936   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2937   if(isComputingTypes)
2938     computeTypes();
2939   declareAsNew();
2940 }
2941
2942 /*!
2943  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2944  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2945  */
2946 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2947                                                                                  _nodal_connec(0),_nodal_connec_index(0),
2948                                                                                 _types(other._types)
2949 {
2950   if(other._nodal_connec)
2951     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2952   if(other._nodal_connec_index)
2953     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2954 }
2955
2956 MEDCouplingUMesh::~MEDCouplingUMesh()
2957 {
2958   if(_nodal_connec)
2959     _nodal_connec->decrRef();
2960   if(_nodal_connec_index)
2961     _nodal_connec_index->decrRef();
2962 }
2963
2964 /*!
2965  * Recomputes a set of cell types of \a this mesh. For more info see
2966  * \ref MEDCouplingUMeshNodalConnectivity.
2967  */
2968 void MEDCouplingUMesh::computeTypes()
2969 {
2970   if(_nodal_connec && _nodal_connec_index)
2971     {
2972       _types.clear();
2973       const int *conn=_nodal_connec->getConstPointer();
2974       const int *connIndex=_nodal_connec_index->getConstPointer();
2975       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2976       if (nbOfElem > 0)
2977         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2978           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2979     }
2980 }
2981
2982 /*!
2983  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2984  */
2985 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2986 {
2987   if(!_nodal_connec_index || !_nodal_connec || !_coords)
2988     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2989 }
2990
2991 /*!
2992  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2993  */
2994 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2995 {
2996   if(!_nodal_connec_index || !_nodal_connec)
2997     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2998 }
2999
3000 /*!
3001  * Returns a number of cells constituting \a this mesh. 
3002  *  \return int - the number of cells in \a this mesh.
3003  *  \throw If the nodal connectivity of cells is not defined.
3004  */
3005 int MEDCouplingUMesh::getNumberOfCells() const
3006
3007   if(_nodal_connec_index)
3008     return _nodal_connec_index->getNumberOfTuples()-1;
3009   else
3010     if(_mesh_dim==-1)
3011       return 1;
3012     else
3013       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3014 }
3015
3016 /*!
3017  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3018  * mesh. For more info see \ref MEDCouplingMeshesPage.
3019  *  \return int - the dimension of \a this mesh.
3020  *  \throw If the mesh dimension is not defined using setMeshDimension().
3021  */
3022 int MEDCouplingUMesh::getMeshDimension() const
3023 {
3024   if(_mesh_dim<-1)
3025     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3026   return _mesh_dim;
3027 }
3028
3029 /*!
3030  * Returns a length of the nodal connectivity array.
3031  * This method is for test reason. Normally the integer returned is not useable by
3032  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3033  *  \return int - the length of the nodal connectivity array.
3034  */
3035 int MEDCouplingUMesh::getMeshLength() const
3036 {
3037   return _nodal_connec->getNbOfElems();
3038 }
3039
3040 /*!
3041  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3042  */
3043 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3044 {
3045   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3046   tinyInfo.push_back(getMeshDimension());
3047   tinyInfo.push_back(getNumberOfCells());
3048   if(_nodal_connec)
3049     tinyInfo.push_back(getMeshLength());
3050   else
3051     tinyInfo.push_back(-1);
3052 }
3053
3054 /*!
3055  * First step of unserialization process.
3056  */
3057 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3058 {
3059   return tinyInfo[6]<=0;
3060 }
3061
3062 /*!
3063  * Second step of serialization process.
3064  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3065  */
3066 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3067 {
3068   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3069   if(tinyInfo[5]!=-1)
3070     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3071 }
3072
3073 /*!
3074  * Third and final step of serialization process.
3075  */
3076 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3077 {
3078   MEDCouplingPointSet::serialize(a1,a2);
3079   if(getMeshDimension()>-1)
3080     {
3081       a1=DataArrayInt::New();
3082       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3083       int *ptA1=a1->getPointer();
3084       const int *conn=getNodalConnectivity()->getConstPointer();
3085       const int *index=getNodalConnectivityIndex()->getConstPointer();
3086       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3087       std::copy(conn,conn+getMeshLength(),ptA1);
3088     }
3089   else
3090     a1=0;
3091 }
3092
3093 /*!
3094  * Second and final unserialization process.
3095  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3096  */
3097 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3098 {
3099   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3100   setMeshDimension(tinyInfo[5]);
3101   if(tinyInfo[7]!=-1)
3102     {
3103       // Connectivity
3104       const int *recvBuffer=a1->getConstPointer();
3105       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3106       myConnecIndex->alloc(tinyInfo[6]+1,1);
3107       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3108       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3109       myConnec->alloc(tinyInfo[7],1);
3110       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3111       setConnectivity(myConnec, myConnecIndex);
3112     }
3113 }
3114
3115 /*!
3116  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3117  * CellIds are given using range specified by a start an end and step.
3118  */
3119 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3120 {
3121   checkFullyDefined();
3122   int ncell=getNumberOfCells();
3123   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3124   ret->_mesh_dim=_mesh_dim;
3125   ret->setCoords(_coords);
3126   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3127   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3128   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3129   int work=start;
3130   const int *conn=_nodal_connec->getConstPointer();
3131   const int *connIndex=_nodal_connec_index->getConstPointer();
3132   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3133     {
3134       if(work>=0 && work<ncell)
3135         {
3136           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3137         }
3138       else
3139         {
3140           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3141           throw INTERP_KERNEL::Exception(oss.str().c_str());
3142         }
3143     }
3144   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3145   int *newConnPtr=newConn->getPointer();
3146   std::set<INTERP_KERNEL::NormalizedCellType> types;
3147   work=start;
3148   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3149     {
3150       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3151       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3152     }
3153   ret->setConnectivity(newConn,newConnI,false);
3154   ret->_types=types;
3155   ret->copyTinyInfoFrom(this);
3156   return ret.retn();
3157 }
3158
3159 /*!
3160  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3161  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3162  * The return newly allocated mesh will share the same coordinates as \a this.
3163  */
3164 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3165 {
3166   checkFullyDefined();
3167   int ncell=getNumberOfCells();
3168   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3169   ret->_mesh_dim=_mesh_dim;
3170   ret->setCoords(_coords);
3171   std::size_t nbOfElemsRet=std::distance(begin,end);
3172   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3173   connIndexRet[0]=0;
3174   const int *conn=_nodal_connec->getConstPointer();
3175   const int *connIndex=_nodal_connec_index->getConstPointer();
3176   int newNbring=0;
3177   for(const int *work=begin;work!=end;work++,newNbring++)
3178     {
3179       if(*work>=0 && *work<ncell)
3180         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3181       else
3182         {
3183           free(connIndexRet);
3184           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3185           throw INTERP_KERNEL::Exception(oss.str().c_str());
3186         }
3187     }
3188   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3189   int *connRetWork=connRet;
3190   std::set<INTERP_KERNEL::NormalizedCellType> types;
3191   for(const int *work=begin;work!=end;work++)
3192     {
3193       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3194       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3195     }
3196   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3197   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3198   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3199   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3200   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3201   ret->_types=types;
3202   ret->copyTinyInfoFrom(this);
3203   return ret.retn();
3204 }
3205
3206 /*!
3207  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3208  * mesh.<br>
3209  * For 1D cells, the returned field contains lengths.<br>
3210  * For 2D cells, the returned field contains areas.<br>
3211  * For 3D cells, the returned field contains volumes.
3212  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3213  *         orientation, i.e. the volume is always positive.
3214  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3215  *         and one time . The caller is to delete this field using decrRef() as it is no
3216  *         more needed.
3217  */
3218 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3219 {
3220   std::string name="MeasureOfMesh_";
3221   name+=getName();
3222   int nbelem=getNumberOfCells();
3223   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3224   field->setName(name.c_str());
3225   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3226   array->alloc(nbelem,1);
3227   double *area_vol=array->getPointer();
3228   field->setArray(array) ; array=0;
3229   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3230   field->synchronizeTimeWithMesh();
3231   if(getMeshDimension()!=-1)
3232     {
3233       int ipt;
3234       INTERP_KERNEL::NormalizedCellType type;
3235       int dim_space=getSpaceDimension();
3236       const double *coords=getCoords()->getConstPointer();
3237       const int *connec=getNodalConnectivity()->getConstPointer();
3238       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3239       for(int iel=0;iel<nbelem;iel++)
3240         {
3241           ipt=connec_index[iel];
3242           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3243           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);
3244         }
3245       if(isAbs)
3246         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3247     }
3248   else
3249     {
3250       area_vol[0]=std::numeric_limits<double>::max();
3251     }
3252   return field.retn();
3253 }
3254
3255 /*!
3256  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3257  * mesh.<br>
3258  * For 1D cells, the returned array contains lengths.<br>
3259  * For 2D cells, the returned array contains areas.<br>
3260  * For 3D cells, the returned array contains volumes.
3261  * This method avoids building explicitly a part of \a this mesh to perform the work.
3262  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3263  *         orientation, i.e. the volume is always positive.
3264  *  \param [in] begin - an array of cell ids of interest.
3265  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3266  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3267  *          delete this array using decrRef() as it is no more needed.
3268  * 
3269  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3270  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3271  *  \sa getMeasureField()
3272  */
3273 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3274 {
3275   std::string name="PartMeasureOfMesh_";
3276   name+=getName();
3277   int nbelem=(int)std::distance(begin,end);
3278   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3279   array->setName(name.c_str());
3280   array->alloc(nbelem,1);
3281   double *area_vol=array->getPointer();
3282   if(getMeshDimension()!=-1)
3283     {
3284       int ipt;
3285       INTERP_KERNEL::NormalizedCellType type;
3286       int dim_space=getSpaceDimension();
3287       const double *coords=getCoords()->getConstPointer();
3288       const int *connec=getNodalConnectivity()->getConstPointer();
3289       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3290       for(const int *iel=begin;iel!=end;iel++)
3291         {
3292           ipt=connec_index[*iel];
3293           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3294           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3295         }
3296       if(isAbs)
3297         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3298     }
3299   else
3300     {
3301       area_vol[0]=std::numeric_limits<double>::max();
3302     }
3303   return array.retn();
3304 }
3305
3306 /*!
3307  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3308  * \a this one. The returned field contains the dual cell volume for each corresponding
3309  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3310  *  the dual mesh in P1 sens of \a this.<br>
3311  * For 1D cells, the returned field contains lengths.<br>
3312  * For 2D cells, the returned field contains areas.<br>
3313  * For 3D cells, the returned field contains volumes.
3314  * This method is useful to check "P1*" conservative interpolators.
3315  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3316  *         orientation, i.e. the volume is always positive.
3317  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3318  *          nodes and one time. The caller is to delete this array using decrRef() as
3319  *          it is no more needed.
3320  */
3321 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3322 {
3323   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3324   std::string name="MeasureOnNodeOfMesh_";
3325   name+=getName();
3326   int nbNodes=getNumberOfNodes();
3327   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3328   double cst=1./((double)getMeshDimension()+1.);
3329   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3330   array->alloc(nbNodes,1);
3331   double *valsToFill=array->getPointer();
3332   std::fill(valsToFill,valsToFill+nbNodes,0.);
3333   const double *values=tmp->getArray()->getConstPointer();
3334   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3336   getReverseNodalConnectivity(da,daInd);
3337   const int *daPtr=da->getConstPointer();
3338   const int *daIPtr=daInd->getConstPointer();
3339   for(int i=0;i<nbNodes;i++)
3340     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3341       valsToFill[i]+=cst*values[*cell];
3342   ret->setMesh(this);
3343   ret->setArray(array);
3344   return ret.retn();
3345 }
3346
3347 /*!
3348  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3349  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3350  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3351  * and are normalized.
3352  * <br> \a this can be either 
3353  * - a  2D mesh in 2D or 3D space or 
3354  * - an 1D mesh in 2D space.
3355  * 
3356  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3357  *          cells and one time. The caller is to delete this field using decrRef() as
3358  *          it is no more needed.
3359  *  \throw If the nodal connectivity of cells is not defined.
3360  *  \throw If the coordinates array is not set.
3361  *  \throw If the mesh dimension is not set.
3362  *  \throw If the mesh and space dimension is not as specified above.
3363  */
3364 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3365 {
3366   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3367     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3368   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3369   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3370   int nbOfCells=getNumberOfCells();
3371   int nbComp=getMeshDimension()+1;
3372   array->alloc(nbOfCells,nbComp);
3373   double *vals=array->getPointer();
3374   const int *connI=_nodal_connec_index->getConstPointer();
3375   const int *conn=_nodal_connec->getConstPointer();
3376   const double *coords=_coords->getConstPointer();
3377   if(getMeshDimension()==2)
3378     {
3379       if(getSpaceDimension()==3)
3380         {
3381           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3382           const double *locPtr=loc->getConstPointer();
3383           for(int i=0;i<nbOfCells;i++,vals+=3)
3384             {
3385               int offset=connI[i];
3386               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3387               double n=INTERP_KERNEL::norm<3>(vals);
3388               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3389             }
3390         }
3391       else
3392         {
3393           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3394           const double *isAbsPtr=isAbs->getArray()->begin();
3395           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3396             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3397         }
3398     }
3399   else//meshdimension==1
3400     {
3401       double tmp[2];
3402       for(int i=0;i<nbOfCells;i++)
3403         {
3404           int offset=connI[i];
3405           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3406           double n=INTERP_KERNEL::norm<2>(tmp);
3407           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3408           *vals++=-tmp[1];
3409           *vals++=tmp[0];
3410         }
3411     }
3412   ret->setArray(array);
3413   ret->setMesh(this);
3414   ret->synchronizeTimeWithSupport();
3415   return ret.retn();
3416 }
3417
3418 /*!
3419  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3420  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3421  * and are normalized.
3422  * <br> \a this can be either 
3423  * - a  2D mesh in 2D or 3D space or 
3424  * - an 1D mesh in 2D space.
3425  * 
3426  * This method avoids building explicitly a part of \a this mesh to perform the work.
3427  *  \param [in] begin - an array of cell ids of interest.
3428  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3429  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3430  *          cells and one time. The caller is to delete this field using decrRef() as
3431  *          it is no more needed.
3432  *  \throw If the nodal connectivity of cells is not defined.
3433  *  \throw If the coordinates array is not set.
3434  *  \throw If the mesh dimension is not set.
3435  *  \throw If the mesh and space dimension is not as specified above.
3436  *  \sa buildOrthogonalField()
3437  *
3438  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3439  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3440  */
3441 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3442 {
3443   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3444     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3445   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3446   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3447   std::size_t nbelems=std::distance(begin,end);
3448   int nbComp=getMeshDimension()+1;
3449   array->alloc((int)nbelems,nbComp);
3450   double *vals=array->getPointer();
3451   const int *connI=_nodal_connec_index->getConstPointer();
3452   const int *conn=_nodal_connec->getConstPointer();
3453   const double *coords=_coords->getConstPointer();
3454   if(getMeshDimension()==2)
3455     {
3456       if(getSpaceDimension()==3)
3457         {
3458           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3459           const double *locPtr=loc->getConstPointer();
3460           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3461             {
3462               int offset=connI[*i];
3463               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3464               double n=INTERP_KERNEL::norm<3>(vals);
3465               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3466             }
3467         }
3468       else
3469         {
3470           for(std::size_t i=0;i<nbelems;i++)
3471             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3472         }
3473     }
3474   else//meshdimension==1
3475     {
3476       double tmp[2];
3477       for(const int *i=begin;i!=end;i++)
3478         {
3479           int offset=connI[*i];
3480           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3481           double n=INTERP_KERNEL::norm<2>(tmp);
3482           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3483           *vals++=-tmp[1];
3484           *vals++=tmp[0];
3485         }
3486     }
3487   ret->setArray(array);
3488   ret->setMesh(this);
3489   ret->synchronizeTimeWithSupport();
3490   return ret.retn();
3491 }
3492
3493 /*!
3494  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3495  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3496  * and are \b not normalized.
3497  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3498  *          cells and one time. The caller is to delete this field using decrRef() as
3499  *          it is no more needed.
3500  *  \throw If the nodal connectivity of cells is not defined.
3501  *  \throw If the coordinates array is not set.
3502  *  \throw If \a this->getMeshDimension() != 1.
3503  *  \throw If \a this mesh includes cells of type other than SEG2.
3504  */
3505 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3506 {
3507    if(getMeshDimension()!=1)
3508     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3509    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3510      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3511    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3512    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3513    int nbOfCells=getNumberOfCells();
3514    int spaceDim=getSpaceDimension();
3515    array->alloc(nbOfCells,spaceDim);
3516    double *pt=array->getPointer();
3517    const double *coo=getCoords()->getConstPointer();
3518    std::vector<int> conn;
3519    conn.reserve(2);
3520    for(int i=0;i<nbOfCells;i++)
3521      {
3522        conn.resize(0);
3523        getNodeIdsOfCell(i,conn);
3524        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3525      }
3526    ret->setArray(array);
3527    ret->setMesh(this);
3528    ret->synchronizeTimeWithSupport();
3529    return ret.retn();   
3530 }
3531
3532 /*!
3533  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3534  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3535  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3536  * from. If a result face is shared by two 3D cells, then the face in included twice in
3537  * the result mesh.
3538  *  \param [in] origin - 3 components of a point defining location of the plane.
3539  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3540  *         must be greater than 1e-6.
3541  *  \param [in] eps - half-thickness of the plane.
3542  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3543  *         producing correspondent 2D cells. The caller is to delete this array
3544  *         using decrRef() as it is no more needed.
3545  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3546  *         not share the node coordinates array with \a this mesh. The caller is to
3547  *         delete this mesh using decrRef() as it is no more needed.  
3548  *  \throw If the coordinates array is not set.
3549  *  \throw If the nodal connectivity of cells is not defined.
3550  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3551  *  \throw If magnitude of \a vec is less than 1e-6.
3552  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3553  *  \throw If \a this includes quadratic cells.
3554  */
3555 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3556 {
3557   checkFullyDefined();
3558   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3559     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3560   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3561   if(candidates->empty())
3562     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3563   std::vector<int> nodes;
3564   DataArrayInt *cellIds1D=0;
3565   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3566   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3567   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3568   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3569   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3570   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3571   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3572   revDesc2=0; revDescIndx2=0;
3573   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3574   revDesc1=0; revDescIndx1=0;
3575   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3576   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3577   //
3578   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3579   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3580     cut3DCurve[*it]=-1;
3581   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3582   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3583   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3584                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3585                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3586   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3587   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3588   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3589   if(cellIds2->empty())
3590     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3591   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3592   ret->setCoords(mDesc1->getCoords());
3593   ret->setConnectivity(conn,connI,true);
3594   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3595   return ret.retn();
3596 }
3597
3598 /*!
3599  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3600 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
3601 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3602 the result mesh.
3603  *  \param [in] origin - 3 components of a point defining location of the plane.
3604  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3605  *         must be greater than 1e-6.
3606  *  \param [in] eps - half-thickness of the plane.
3607  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3608  *         producing correspondent segments. The caller is to delete this array
3609  *         using decrRef() as it is no more needed.
3610  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3611  *         mesh in 3D space. This mesh does not share the node coordinates array with
3612  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3613  *         no more needed. 
3614  *  \throw If the coordinates array is not set.
3615  *  \throw If the nodal connectivity of cells is not defined.
3616  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3617  *  \throw If magnitude of \a vec is less than 1e-6.
3618  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3619  *  \throw If \a this includes quadratic cells.
3620  */
3621 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3622 {
3623   checkFullyDefined();
3624   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3625     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3626   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3627   if(candidates->empty())
3628     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3629   std::vector<int> nodes;
3630   DataArrayInt *cellIds1D=0;
3631   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3632   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3633   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3634   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3635   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3636   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3637   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3638   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3639   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3640   //
3641   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3642   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3643     cut3DCurve[*it]=-1;
3644   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3645   int ncellsSub=subMesh->getNumberOfCells();
3646   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3647   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3648                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3649                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3650   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3651   conn->alloc(0,1);
3652   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3653   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3654   for(int i=0;i<ncellsSub;i++)
3655     {
3656       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3657         {
3658           if(cut3DSurf[i].first!=-2)
3659             {
3660               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3661               connI->pushBackSilent(conn->getNumberOfTuples());
3662               cellIds2->pushBackSilent(i);
3663             }
3664           else
3665             {
3666               int cellId3DSurf=cut3DSurf[i].second;
3667               int offset=nodalI[cellId3DSurf]+1;
3668               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3669               for(int j=0;j<nbOfEdges;j++)
3670                 {
3671                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3672                   connI->pushBackSilent(conn->getNumberOfTuples());
3673                   cellIds2->pushBackSilent(cellId3DSurf);
3674                 }
3675             }
3676         }
3677     }
3678   if(cellIds2->empty())
3679     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3680   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3681   ret->setCoords(mDesc1->getCoords());
3682   ret->setConnectivity(conn,connI,true);
3683   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3684   return ret.retn();
3685 }
3686
3687 /*!
3688  * Finds cells whose bounding boxes intersect a given plane.
3689  *  \param [in] origin - 3 components of a point defining location of the plane.
3690  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3691  *         must be greater than 1e-6.
3692  *  \param [in] eps - half-thickness of the plane.
3693  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3694  *         cells. The caller is to delete this array using decrRef() as it is no more
3695  *         needed.
3696  *  \throw If the coordinates array is not set.
3697  *  \throw If the nodal connectivity of cells is not defined.
3698  *  \throw If \a this->getSpaceDimension() != 3.
3699  *  \throw If magnitude of \a vec is less than 1e-6.
3700  *  \sa buildSlice3D()
3701  */
3702 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3703 {
3704   checkFullyDefined();
3705   if(getSpaceDimension()!=3)
3706     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3707   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3708   if(normm<1e-6)
3709     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3710   double vec2[3];
3711   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3712   double angle=acos(vec[2]/normm);
3713   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3714   double bbox[6];
3715   if(angle>eps)
3716     {
3717       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3718       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3719       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3720       mw->setCoords(coo);
3721       mw->getBoundingBox(bbox);
3722       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3723       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3724     }
3725   else
3726     {
3727       getBoundingBox(bbox);
3728       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3729       cellIds=getCellsInBoundingBox(bbox,eps);
3730     }
3731   return cellIds.retn();
3732 }
3733
3734 /*!
3735  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3736  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3737  * No consideration of coordinate is done by this method.
3738  * 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)
3739  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3740  */
3741 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3742 {
3743   if(getMeshDimension()!=1)
3744     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3745   int nbCells=getNumberOfCells();
3746   if(nbCells<1)
3747     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3748   const int *connI=_nodal_connec_index->getConstPointer();
3749   const int *conn=_nodal_connec->getConstPointer();
3750   int ref=conn[connI[0]+2];
3751   for(int i=1;i<nbCells;i++)
3752     {
3753       if(conn[connI[i]+1]!=ref)
3754         return false;
3755       ref=conn[connI[i]+2];
3756     }
3757   return true;
3758 }
3759
3760 /*!
3761  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3762  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3763  * \param pt reference point of the line
3764  * \param v normalized director vector of the line
3765  * \param eps max precision before throwing an exception
3766  * \param res output of size this->getNumberOfCells
3767  */
3768 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3769 {
3770   if(getMeshDimension()!=1)
3771     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3772    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3773      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3774    if(getSpaceDimension()!=3)
3775      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3776    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3777    const double *fPtr=f->getArray()->getConstPointer();
3778    double tmp[3];
3779    for(int i=0;i<getNumberOfCells();i++)
3780      {
3781        const double *tmp1=fPtr+3*i;
3782        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3783        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3784        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3785        double n1=INTERP_KERNEL::norm<3>(tmp);
3786        n1/=INTERP_KERNEL::norm<3>(tmp1);
3787        if(n1>eps)
3788          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3789      }
3790    const double *coo=getCoords()->getConstPointer();
3791    for(int i=0;i<getNumberOfNodes();i++)
3792      {
3793        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3794        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3795        res[i]=std::accumulate(tmp,tmp+3,0.);
3796      }
3797 }
3798
3799 /*!
3800  * 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. 
3801  * \a this is expected to be a mesh so that its space dimension is equal to its
3802  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3803  * 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).
3804  
3805  * 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
3806  * 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).
3807  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3808  *
3809  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3810  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3811  *
3812  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3813  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3814  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3815  * \return the positive value of the distance.
3816  * \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
3817  * dimension - 1.
3818  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3819  */
3820 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
3821 {
3822   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3823   if(meshDim!=spaceDim-1)
3824     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3825   if(meshDim!=2 && meshDim!=1)
3826     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3827   checkFullyDefined();
3828   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3829     { 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()); }
3830   DataArrayInt *ret1=0;
3831   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3832   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3833   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3834   cellId=*ret1Safe->begin();
3835   return *ret0->begin();
3836 }
3837
3838 /*!
3839  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3840  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3841  * 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
3842  * 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).
3843  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3844  * 
3845  * \a this is expected to be a mesh so that its space dimension is equal to its
3846  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3847  * 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).
3848  *
3849  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3850  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3851  *
3852  * \param [in] pts the list of points in which each tuple represents a point
3853  * \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.
3854  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3855  * \throw if number of components of \a pts is not equal to the space dimension.
3856  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3857  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3858  */
3859 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
3860 {
3861   if(!pts)
3862     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3863   pts->checkAllocated();
3864   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3865   if(meshDim!=spaceDim-1)
3866     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3867   if(meshDim!=2 && meshDim!=1)
3868     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3869   if(pts->getNumberOfComponents()!=spaceDim)
3870     {
3871       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3872       throw INTERP_KERNEL::Exception(oss.str().c_str());
3873     }
3874   checkFullyDefined();
3875   int nbCells=getNumberOfCells();
3876   if(nbCells==0)
3877     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3878   int nbOfPts=pts->getNumberOfTuples();
3879   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3881   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3882   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3883   std::vector<double> bbox;
3884   getBoundingBoxForBBTree(bbox);
3885   switch(spaceDim)
3886     {
3887     case 3:
3888       {
3889         BBTreeDst<3> myTree(&bbox[0],0,0,nbCells);
3890         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3891           {
3892             double x=std::numeric_limits<double>::max();
3893             std::vector<int> elems;
3894             myTree.getMinDistanceOfMax(ptsPtr,x);
3895             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3896             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3897           }
3898         break;
3899       }
3900     case 2:
3901       {
3902         BBTreeDst<2> myTree(&bbox[0],0,0,nbCells);
3903         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3904           {
3905             double x=std::numeric_limits<double>::max();
3906             std::vector<int> elems;
3907             myTree.getMinDistanceOfMax(ptsPtr,x);
3908             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3909             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3910           }
3911         break;
3912       }
3913     default:
3914       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3915     }
3916   cellIds=ret1.retn();
3917   return ret0.retn();
3918 }
3919
3920 /*!
3921  * \param [in] pt the start pointer (included) of the coordinates of the point
3922  * \param [in] cellIdsBg the start pointer (included) of cellIds
3923  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3924  * \param [in] nc nodal connectivity
3925  * \param [in] ncI nodal connectivity index
3926  * \param [in,out] ret0 the min distance between \a this and the external input point
3927  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3928  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3929  */
3930 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) throw(INTERP_KERNEL::Exception)
3931 {
3932   cellId=-1;
3933   ret0=std::numeric_limits<double>::max();
3934   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3935     {
3936       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3937         {
3938         case INTERP_KERNEL::NORM_TRI3:
3939           {
3940             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3941             if(tmp<ret0)
3942               { ret0=tmp; cellId=*zeCell; }
3943             break;
3944           }
3945         case INTERP_KERNEL::NORM_QUAD4:
3946         case INTERP_KERNEL::NORM_POLYGON:
3947           {
3948             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3949             if(tmp<ret0)
3950               { ret0=tmp; cellId=*zeCell; }
3951             break;
3952           }
3953         default:
3954           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3955         }
3956     }
3957 }
3958
3959 /*!
3960  * \param [in] pt the start pointer (included) of the coordinates of the point
3961  * \param [in] cellIdsBg the start pointer (included) of cellIds
3962  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3963  * \param [in] nc nodal connectivity
3964  * \param [in] ncI nodal connectivity index
3965  * \param [in,out] ret0 the min distance between \a this and the external input point
3966  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3967  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3968  */
3969 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) throw(INTERP_KERNEL::Exception)
3970 {
3971   cellId=-1;
3972   ret0=std::numeric_limits<double>::max();
3973   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3974     {
3975        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3976         {
3977         case INTERP_KERNEL::NORM_SEG2:
3978           {
3979             std::size_t uselessEntry=0;
3980             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
3981             tmp=sqrt(tmp);
3982             if(tmp<ret0)
3983               { ret0=tmp; cellId=*zeCell; }
3984             break;
3985           }
3986         default:
3987           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3988         }
3989     }
3990 }
3991
3992 /*!
3993  * Finds cells in contact with a ball (i.e. a point with precision). 
3994  * \warning This method is suitable if the caller intends to evaluate only one
3995  *          point, for more points getCellsContainingPoints() is recommended as it is
3996  *          faster. 
3997  *  \param [in] pos - array of coordinates of the ball central point.
3998  *  \param [in] eps - ball radius.
3999  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4000  *         if there are no such cells.
4001  *  \throw If the coordinates array is not set.
4002  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4003  */
4004 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4005 {
4006   std::vector<int> elts;
4007   getCellsContainingPoint(pos,eps,elts);
4008   if(elts.empty())
4009     return -1;
4010   return elts.front();
4011 }
4012
4013 /*!
4014  * Finds cells in contact with a ball (i.e. a point with precision).
4015  * \warning This method is suitable if the caller intends to evaluate only one
4016  *          point, for more points getCellsContainingPoints() is recommended as it is
4017  *          faster. 
4018  *  \param [in] pos - array of coordinates of the ball central point.
4019  *  \param [in] eps - ball radius.
4020  *  \param [in,out] elts - vector returning ids of the found cells. It is cleared
4021  *         before inserting ids.
4022  *  \throw If the coordinates array is not set.
4023  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4024  *
4025  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4026  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4027  */
4028 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4029 {
4030   std::vector<int> eltsIndex;
4031   getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
4032 }
4033
4034 /// @cond INTERNAL
4035
4036 namespace ParaMEDMEM
4037 {
4038   template<const int SPACEDIMM>
4039   class DummyClsMCUG
4040   {
4041   public:
4042     static const int MY_SPACEDIM=SPACEDIMM;
4043     static const int MY_MESHDIM=8;
4044     typedef int MyConnType;
4045     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4046     // begin
4047     // useless, but for windows compilation ...
4048     const double* getCoordinatesPtr() const { return 0; }
4049     const int* getConnectivityPtr() const { return 0; }
4050     const int* getConnectivityIndexPtr() const { return 0; }
4051     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4052     // end
4053   };
4054
4055   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4056   {
4057     INTERP_KERNEL::Edge *ret=0;
4058     switch(typ)
4059       {
4060       case INTERP_KERNEL::NORM_SEG2:
4061         {
4062           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4063           break;
4064         }
4065       case INTERP_KERNEL::NORM_SEG3:
4066         {
4067           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4068           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4069           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4070           bool colinearity=inters.areColinears();
4071           delete e1; delete e2;
4072           if(colinearity)
4073             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4074           else
4075             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4076           mapp2[bg[2]].second=false;
4077           break;
4078         }
4079       default:
4080         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4081       }
4082     return ret;
4083   }
4084
4085   /*!
4086    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed be the sub set of cells in 'candidates' and the global mesh 'mDesc'.
4087    * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4088    * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4089    */
4090   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4091   {
4092     mapp.clear();
4093     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.
4094     const double *coo=mDesc->getCoords()->getConstPointer();
4095     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4096     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4097     std::set<int> s;
4098     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4099       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4100     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4101       {
4102         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4103         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4104       }
4105     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4106     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4107       {
4108         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4109         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4110       }
4111     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4112       {
4113         if((*it2).second.second)
4114           mapp[(*it2).second.first]=(*it2).first;
4115         ((*it2).second.first)->decrRef();
4116       }
4117     return ret;
4118   }
4119
4120   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4121   {
4122     if(nodeId>=offset2)
4123       {
4124         int locId=nodeId-offset2;
4125         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4126       }
4127     if(nodeId>=offset1)
4128       {
4129         int locId=nodeId-offset1;
4130         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4131       }
4132     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4133   }
4134
4135   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4136                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4137                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4138   {
4139     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4140       {
4141         int eltId1=abs(*desc1)-1;
4142         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4143           {
4144             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4145             if(it==mappRev.end())
4146               {
4147                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4148                 mapp[node]=*it1;
4149                 mappRev[*it1]=node;
4150               }
4151           }
4152       }
4153   }
4154 }
4155
4156 /// @endcond
4157
4158 template<int SPACEDIM>
4159 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4160                                                    double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4161 {
4162   std::vector<double> bbox;
4163   eltsIndex.resize(nbOfPoints+1);
4164   eltsIndex[0]=0;
4165   elts.clear();
4166   getBoundingBoxForBBTree(bbox);
4167   int nbOfCells=getNumberOfCells();
4168   const int *conn=_nodal_connec->getConstPointer();
4169   const int *connI=_nodal_connec_index->getConstPointer();
4170   double bb[2*SPACEDIM];
4171   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4172   for(int i=0;i<nbOfPoints;i++)
4173     {
4174       eltsIndex[i+1]=eltsIndex[i];
4175       for(int j=0;j<SPACEDIM;j++)
4176         {
4177           bb[2*j]=pos[SPACEDIM*i+j];
4178           bb[2*j+1]=pos[SPACEDIM*i+j];
4179         }
4180       std::vector<int> candidates;
4181       myTree.getIntersectingElems(bb,candidates);
4182       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4183         {
4184           int sz=connI[(*iter)+1]-connI[*iter]-1;
4185           if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4186                                                                                                (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4187                                                                                                coords,conn+connI[*iter]+1,sz,eps))
4188             {
4189               eltsIndex[i+1]++;
4190               elts.push_back(*iter);
4191             }
4192         }
4193     }
4194 }
4195 /*!
4196  * Finds cells in contact with several balls (i.e. points with precision).
4197  * This method is an extension of getCellContainingPoint() and
4198  * getCellsContainingPoint() for the case of multiple points.
4199  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4200  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4201  *         this->getSpaceDimension() * \a nbOfPoints 
4202  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4203  *  \param [in] eps - radius of balls (i.e. the precision).
4204  *  \param [in,out] elts - vector returning ids of found cells.
4205  *  \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4206  *         dividing cell ids in \a elts into groups each referring to one
4207  *         point. Its every element (except the last one) is an index pointing to the
4208  *         first id of a group of cells. For example cells in contact with the *i*-th
4209  *         point are described by following range of indices:
4210  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4211  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4212  *         Number of cells in contact with the *i*-th point is
4213  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4214  *  \throw If the coordinates array is not set.
4215  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4216  *
4217  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4218  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4219  */
4220 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4221                                                 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4222 {
4223   int spaceDim=getSpaceDimension();
4224   int mDim=getMeshDimension();
4225   if(spaceDim==3)
4226     {
4227       if(mDim==3)
4228         {
4229           const double *coords=_coords->getConstPointer();
4230           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4231         }
4232       /*else if(mDim==2)
4233         {
4234           
4235         }*/
4236       else
4237         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4238     }
4239   else if(spaceDim==2)
4240     {
4241       if(mDim==2)
4242         {
4243           const double *coords=_coords->getConstPointer();
4244           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4245         }
4246       else
4247         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4248     }
4249   else if(spaceDim==1)
4250     {
4251       if(mDim==1)
4252         {
4253           const double *coords=_coords->getConstPointer();
4254           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4255         }
4256       else
4257         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4258     }
4259   else
4260     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4261 }
4262
4263 /*!
4264  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4265  * least two its edges intersect each other anywhere except their extremities. An
4266  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4267  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4268  *         cleared before filling in.
4269  *  \param [in] eps - precision.
4270  *  \throw If \a this->getMeshDimension() != 2.
4271  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4272  */
4273 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4274 {
4275   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4276   if(getMeshDimension()!=2)
4277     throw INTERP_KERNEL::Exception(msg);
4278   int spaceDim=getSpaceDimension();
4279   if(spaceDim!=2 && spaceDim!=3)
4280     throw INTERP_KERNEL::Exception(msg);
4281   const int *conn=_nodal_connec->getConstPointer();
4282   const int *connI=_nodal_connec_index->getConstPointer();
4283   int nbOfCells=getNumberOfCells();
4284   std::vector<double> cell2DinS2;
4285   for(int i=0;i<nbOfCells;i++)
4286     {
4287       int offset=connI[i];
4288       int nbOfNodesForCell=connI[i+1]-offset-1;
4289       if(nbOfNodesForCell<=3)
4290         continue;
4291       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4292       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4293       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4294         cells.push_back(i);
4295       cell2DinS2.clear();
4296     }
4297 }
4298
4299 /*!
4300  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4301  *
4302  * 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.
4303  * 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.
4304  * 
4305  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4306  * This convex envelop is computed using Jarvis march algorithm.
4307  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4308  * 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)
4309  * 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.
4310  *
4311  * \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.
4312  */
4313 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4314 {
4315   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4316     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4317   checkFullyDefined();
4318   const double *coords=getCoords()->getConstPointer();
4319   int nbOfCells=getNumberOfCells();
4320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4321   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4322   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4323   int *workIndexOut=nodalConnecIndexOut->getPointer();
4324   *workIndexOut=0;
4325   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4326   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4327   std::set<INTERP_KERNEL::NormalizedCellType> types;
4328   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4329   isChanged->alloc(0,1);
4330   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4331     {
4332       int pos=nodalConnecOut->getNumberOfTuples();
4333       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4334         isChanged->pushBackSilent(i);
4335       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4336       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4337     }
4338   if(isChanged->empty())
4339     return 0;
4340   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4341   _types=types;
4342   return isChanged.retn();
4343 }
4344
4345 /*!
4346  * This method is \b NOT const because it can modify \a this.
4347  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4348  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4349  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4350  * \b 1 for translation and rotation around point of 'mesh1D'.
4351  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4352  */
4353 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4354 {
4355   checkFullyDefined();
4356   mesh1D->checkFullyDefined();
4357   if(!mesh1D->isContiguous1D())
4358     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4359   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4360     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4361   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4362     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4363   if(mesh1D->getMeshDimension()!=1)
4364     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4365   bool isQuad=false;
4366   if(isPresenceOfQuadratic())
4367     {
4368       if(mesh1D->isFullyQuadratic())
4369         isQuad=true;
4370       else
4371         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4372     }
4373   zipCoords();
4374   int oldNbOfNodes=getNumberOfNodes();
4375   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4376   switch(policy)
4377     {
4378     case 0:
4379       {
4380         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4381         break;
4382       }
4383     case 1:
4384       {
4385         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4386         break;
4387       }
4388     default:
4389       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4390     }
4391   setCoords(newCoords);
4392   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4393   updateTime();
4394   return ret.retn();
4395 }
4396
4397 /*!
4398  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4399  * If it is not the case an exception will be thrown.
4400  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4401  * intersection of plane defined by ('origin','vec').
4402  * This method has one in/out parameter : 'cut3DCurve'.
4403  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4404  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4405  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4406  * This method will throw an exception if \a this contains a non linear segment.
4407  */
4408 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4409 {
4410   checkFullyDefined();
4411   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4412     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4413   int ncells=getNumberOfCells();
4414   int nnodes=getNumberOfNodes();
4415   double vec2[3],vec3[3],vec4[3];
4416   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4417   if(normm<1e-6)
4418     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4419   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4420   const int *conn=_nodal_connec->getConstPointer();
4421   const int *connI=_nodal_connec_index->getConstPointer();
4422   const double *coo=_coords->getConstPointer();
4423   std::vector<double> addCoo;
4424   for(int i=0;i<ncells;i++)
4425     {
4426       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4427         {
4428           if(cut3DCurve[i]==-2)
4429             {
4430               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4431               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];
4432               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4433               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4434               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4435                 {
4436                   const double *st2=coo+3*st;
4437                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4438                   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]));
4439                   if(pos>eps && pos<1-eps)
4440                     {
4441                       int nNode=((int)addCoo.size())/3;
4442                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4443                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4444                       cut3DCurve[i]=nnodes+nNode;
4445                     }
4446                 }
4447             }
4448         }
4449       else
4450         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4451     }
4452   if(!addCoo.empty())
4453     {
4454       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4455       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4456       coo2->alloc(newNbOfNodes,3);
4457       double *tmp=coo2->getPointer();
4458       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4459       std::copy(addCoo.begin(),addCoo.end(),tmp);
4460       DataArrayDouble::SetArrayIn(coo2,_coords);
4461     }
4462 }
4463
4464 /*!
4465  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4466  * \param mesh1D is the input 1D mesh used for translation computation.
4467  * \return newCoords new coords filled by this method. 
4468  */
4469 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4470 {
4471   int oldNbOfNodes=getNumberOfNodes();
4472   int nbOf1DCells=mesh1D->getNumberOfCells();
4473   int spaceDim=getSpaceDimension();
4474   DataArrayDouble *ret=DataArrayDouble::New();
4475   std::vector<bool> isQuads;
4476   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4477   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4478   double *retPtr=ret->getPointer();
4479   const double *coords=getCoords()->getConstPointer();
4480   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4481   std::vector<int> v;
4482   std::vector<double> c;
4483   double vec[3];
4484   v.reserve(3);
4485   c.reserve(6);
4486   for(int i=0;i<nbOf1DCells;i++)
4487     {
4488       v.resize(0);
4489       mesh1D->getNodeIdsOfCell(i,v);
4490       c.resize(0);
4491       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4492       mesh1D->getCoordinatesOfNode(v[0],c);
4493       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4494       for(int j=0;j<oldNbOfNodes;j++)
4495         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4496       if(isQuad)
4497         {
4498           c.resize(0);
4499           mesh1D->getCoordinatesOfNode(v[1],c);
4500           mesh1D->getCoordinatesOfNode(v[0],c);
4501           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4502           for(int j=0;j<oldNbOfNodes;j++)
4503             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4504         }
4505     }
4506   ret->copyStringInfoFrom(*getCoords());
4507   return ret;
4508 }
4509
4510 /*!
4511  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4512  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4513  * \return newCoords new coords filled by this method. 
4514  */
4515 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4516 {
4517   if(mesh1D->getSpaceDimension()==2)
4518     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4519   if(mesh1D->getSpaceDimension()==3)
4520     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4521   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4522 }
4523
4524 /*!
4525  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4526  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4527  * \return newCoords new coords filled by this method. 
4528  */
4529 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4530 {
4531   if(isQuad)
4532     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4533   int oldNbOfNodes=getNumberOfNodes();
4534   int nbOf1DCells=mesh1D->getNumberOfCells();
4535   if(nbOf1DCells<2)
4536     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4537   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4538   int nbOfLevsInVec=nbOf1DCells+1;
4539   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4540   double *retPtr=ret->getPointer();
4541   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4542   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4543   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4544   tmp->setCoords(tmp2);
4545   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4546   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4547   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4548   for(int i=1;i<nbOfLevsInVec;i++)
4549     {
4550       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4551       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4552       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4553       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4554       tmp->translate(vec);
4555       double tmp3[2],radius,alpha,alpha0;
4556       const double *p0=i+1<nbOfLevsInVec?begin:third;
4557       const double *p1=i+1<nbOfLevsInVec?end:begin;
4558       const double *p2=i+1<nbOfLevsInVec?third:end;
4559       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4560       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]);
4561       double angle=acos(cosangle/(radius*radius));
4562       tmp->rotate(end,0,angle);
4563       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4564     }
4565   return ret.retn();
4566 }
4567
4568 /*!
4569  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4570  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4571  * \return newCoords new coords filled by this method. 
4572  */
4573 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4574 {
4575   if(isQuad)
4576     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4577   int oldNbOfNodes=getNumberOfNodes();
4578   int nbOf1DCells=mesh1D->getNumberOfCells();
4579   if(nbOf1DCells<2)
4580     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4581   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4582   int nbOfLevsInVec=nbOf1DCells+1;
4583   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4584   double *retPtr=ret->getPointer();
4585   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4586   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4587   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4588   tmp->setCoords(tmp2);
4589   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4590   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4591   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4592   for(int i=1;i<nbOfLevsInVec;i++)
4593     {
4594       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4595       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4596       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4597       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4598       tmp->translate(vec);
4599       double tmp3[2],radius,alpha,alpha0;
4600       const double *p0=i+1<nbOfLevsInVec?begin:third;
4601       const double *p1=i+1<nbOfLevsInVec?end:begin;
4602       const double *p2=i+1<nbOfLevsInVec?third:end;
4603       double vecPlane[3]={
4604         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4605         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4606         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4607       };
4608       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4609       if(norm>1.e-7)
4610         {
4611           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4612           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4613           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4614           double s2=norm2;
4615           double c2=cos(asin(s2));
4616           double m[3][3]={
4617             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4618             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4619             {-vec2[1]*s2, vec2[0]*s2, c2}
4620           };
4621           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]};
4622           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]};
4623           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]};
4624           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4625           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]);
4626           double angle=acos(cosangle/(radius*radius));
4627           tmp->rotate(end,vecPlane,angle);
4628           
4629         }
4630       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4631     }
4632   return ret.retn();
4633 }
4634
4635 /*!
4636  * This method is private because not easy to use for end user. This method is const contrary to
4637  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4638  * the coords sorted slice by slice.
4639  * \param isQuad specifies presence of quadratic cells.
4640  */
4641 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4642 {
4643   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4644   int nbOf2DCells=getNumberOfCells();
4645   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4646   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4647   const int *conn=_nodal_connec->getConstPointer();
4648   const int *connI=_nodal_connec_index->getConstPointer();
4649   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4650   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4651   newConnI->alloc(nbOf3DCells+1,1);
4652   int *newConnIPtr=newConnI->getPointer();
4653   *newConnIPtr++=0;
4654   std::vector<int> newc;
4655   for(int j=0;j<nbOf2DCells;j++)
4656     {
4657       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4658       *newConnIPtr++=(int)newc.size();
4659     }
4660   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4661   int *newConnPtr=newConn->getPointer();
4662   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4663   newConnIPtr=newConnI->getPointer();
4664   for(int iz=0;iz<nbOf1DCells;iz++)
4665     {
4666       if(iz!=0)
4667         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4668       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4669         {
4670           int icell=(int)(iter-newc.begin());
4671           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4672             {
4673               if(*iter!=-1)
4674                 *newConnPtr=(*iter)+iz*deltaPerLev;
4675               else
4676                 *newConnPtr=-1;
4677             }
4678           else
4679             *newConnPtr=(*iter);
4680         }
4681     }
4682   ret->setConnectivity(newConn,newConnI,true);
4683   ret->setCoords(getCoords());
4684   return ret;
4685 }
4686
4687 /*!
4688  * Checks if \a this mesh is constituted by only quadratic cells.
4689  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4690  *  \throw If the coordinates array is not set.
4691  *  \throw If the nodal connectivity of cells is not defined.
4692  */
4693 bool MEDCouplingUMesh::isFullyQuadratic() const
4694 {
4695   checkFullyDefined();
4696   bool ret=true;
4697   int nbOfCells=getNumberOfCells();
4698   for(int i=0;i<nbOfCells && ret;i++)
4699     {
4700       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4701       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4702       ret=cm.isQuadratic();
4703     }
4704   return ret;
4705 }
4706
4707 /*!
4708  * Checks if \a this mesh includes any quadratic cell.
4709  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4710  *  \throw If the coordinates array is not set.
4711  *  \throw If the nodal connectivity of cells is not defined.
4712  */
4713 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4714 {
4715   checkFullyDefined();
4716   bool ret=false;
4717   int nbOfCells=getNumberOfCells();
4718   for(int i=0;i<nbOfCells && !ret;i++)
4719     {
4720       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4721       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4722       ret=cm.isQuadratic();
4723     }
4724   return ret;
4725 }
4726
4727 /*!
4728  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4729  * this mesh, it remains unchanged.
4730  *  \throw If the coordinates array is not set.
4731  *  \throw If the nodal connectivity of cells is not defined.
4732  */
4733 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4734 {
4735   checkFullyDefined();
4736   int nbOfCells=getNumberOfCells();
4737   int delta=0;
4738   const int *iciptr=_nodal_connec_index->getConstPointer();
4739   for(int i=0;i<nbOfCells;i++)
4740     {
4741       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4742       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4743       if(cm.isQuadratic())
4744         {
4745           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4746           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4747           if(!cml.isDynamic())
4748             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4749           else
4750             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4751         }
4752     }
4753   if(delta==0)
4754     return ;
4755   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4756   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4757   const int *icptr=_nodal_connec->getConstPointer();
4758   newConn->alloc(getMeshLength()-delta,1);
4759   newConnI->alloc(nbOfCells+1,1);
4760   int *ocptr=newConn->getPointer();
4761   int *ociptr=newConnI->getPointer();
4762   *ociptr=0;
4763   _types.clear();
4764   for(int i=0;i<nbOfCells;i++,ociptr++)
4765     {
4766       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4767       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4768       if(!cm.isQuadratic())
4769         {
4770           _types.insert(type);
4771           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4772           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4773         }
4774       else
4775         {
4776           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4777           _types.insert(typel);
4778           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4779           int newNbOfNodes=cml.getNumberOfNodes();
4780           if(cml.isDynamic())
4781             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4782           *ocptr++=(int)typel;
4783           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4784           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4785         }
4786     }
4787   setConnectivity(newConn,newConnI,false);
4788 }
4789
4790 /*!
4791  * This method converts all linear cell in \a this to quadratic one.
4792  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4793  * 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)
4794  * 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.
4795  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4796  * end of the existing coordinates.
4797  * 
4798  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4799  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4800  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4801  * 
4802  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4803  *
4804  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4805  */
4806 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4807 {
4808   DataArrayInt *conn=0,*connI=0;
4809   DataArrayDouble *coords=0;
4810   std::set<INTERP_KERNEL::NormalizedCellType> types;
4811   checkFullyDefined();
4812   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4813   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4814   int meshDim=getMeshDimension();
4815   switch(conversionType)
4816     {
4817     case 0:
4818       switch(meshDim)
4819         {
4820         case 1:
4821           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4822           connSafe=conn; connISafe=connI; coordsSafe=coords;
4823           break;
4824         case 2:
4825           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4826           connSafe=conn; connISafe=connI; coordsSafe=coords;
4827           break;
4828         case 3:
4829           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4830           connSafe=conn; connISafe=connI; coordsSafe=coords;
4831           break;
4832         default:
4833           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4834         }
4835       break;
4836     case 1:
4837       {
4838         switch(meshDim)
4839         {
4840         case 1:
4841           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4842           connSafe=conn; connISafe=connI; coordsSafe=coords;
4843           break;
4844         case 2:
4845           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4846           connSafe=conn; connISafe=connI; coordsSafe=coords;
4847           break;
4848         case 3:
4849           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4850           connSafe=conn; connISafe=connI; coordsSafe=coords;
4851           break;
4852         default:
4853           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4854         }
4855         break;
4856       }
4857     default:
4858       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4859     }
4860   setConnectivity(connSafe,connISafe,false);
4861   _types=types;
4862   setCoords(coordsSafe);
4863   return ret.retn();
4864 }
4865
4866 /*!
4867  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4868  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4869  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4870  */
4871 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4872 {
4873   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4874   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4875   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4876   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4877   int nbOfCells=getNumberOfCells();
4878   int nbOfNodes=getNumberOfNodes();
4879   const int *cPtr=_nodal_connec->getConstPointer();
4880   const int *icPtr=_nodal_connec_index->getConstPointer();
4881   int lastVal=0,offset=nbOfNodes;
4882   for(int i=0;i<nbOfCells;i++,icPtr++)
4883     {
4884       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4885       if(type==INTERP_KERNEL::NORM_SEG2)
4886         {
4887           types.insert(INTERP_KERNEL::NORM_SEG3);
4888           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4889           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4890           newConn->pushBackSilent(offset++);
4891           lastVal+=4;
4892           newConnI->pushBackSilent(lastVal);
4893           ret->pushBackSilent(i);
4894         }
4895       else
4896         {
4897           types.insert(type);
4898           lastVal+=(icPtr[1]-icPtr[0]);
4899           newConnI->pushBackSilent(lastVal);
4900           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4901         }
4902     }
4903   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4904   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4905   return ret.retn();
4906 }
4907
4908 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 throw(INTERP_KERNEL::Exception)
4909 {
4910   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4911   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4912   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4913   //
4914   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4915   DataArrayInt *conn1D=0,*conn1DI=0;
4916   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4917   DataArrayDouble *coordsTmp=0;
4918   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4919   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4920   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4921   const int *c1DPtr=conn1D->begin();
4922   const int *c1DIPtr=conn1DI->begin();
4923   int nbOfCells=getNumberOfCells();
4924   const int *cPtr=_nodal_connec->getConstPointer();
4925   const int *icPtr=_nodal_connec_index->getConstPointer();
4926   int lastVal=0;
4927   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4928     {
4929       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4930       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4931       if(!cm.isQuadratic())
4932         {
4933           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4934           types.insert(typ2); newConn->pushBackSilent(typ2);
4935           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4936           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4937             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4938           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4939           newConnI->pushBackSilent(lastVal);
4940           ret->pushBackSilent(i);
4941         }
4942       else
4943         {
4944           types.insert(typ);
4945           lastVal+=(icPtr[1]-icPtr[0]);
4946           newConnI->pushBackSilent(lastVal);
4947           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4948         }
4949     }
4950   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4951   return ret.retn();
4952 }
4953
4954 /*!
4955  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4956  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4957  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4958  */
4959 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4960 {
4961   
4962   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4963   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4964   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4965 }
4966
4967 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4968 {
4969   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4970   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4971   //
4972   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4973   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4974   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4975   //
4976   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4977   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4978   DataArrayInt *conn1D=0,*conn1DI=0;
4979   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4980   DataArrayDouble *coordsTmp=0;
4981   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4982   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4984   const int *c1DPtr=conn1D->begin();
4985   const int *c1DIPtr=conn1DI->begin();
4986   int nbOfCells=getNumberOfCells();
4987   const int *cPtr=_nodal_connec->getConstPointer();
4988   const int *icPtr=_nodal_connec_index->getConstPointer();
4989   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4990   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4991     {
4992       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4993       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4994       if(!cm.isQuadratic())
4995         {
4996           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4997           types.insert(typ2); newConn->pushBackSilent(typ2);
4998           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4999           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5000             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5001           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5002           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5003           newConnI->pushBackSilent(lastVal);
5004           ret->pushBackSilent(i);
5005         }
5006       else
5007         {
5008           types.insert(typ);
5009           lastVal+=(icPtr[1]-icPtr[0]);
5010           newConnI->pushBackSilent(lastVal);
5011           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5012         }
5013     }
5014   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5015   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5016   return ret.retn();
5017 }
5018
5019 /*!
5020  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5021  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5022  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5023  */
5024 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5025 {
5026   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5027   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5028   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5029 }
5030
5031 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5032 {
5033   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5034   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5035   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5036   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5037   //
5038   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5039   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5040   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5041   //
5042   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5043   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5044   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5045   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5046   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5047   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5048   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5049   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5050   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5051   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5052   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5053   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5054   int nbOfCells=getNumberOfCells();
5055   const int *cPtr=_nodal_connec->getConstPointer();
5056   const int *icPtr=_nodal_connec_index->getConstPointer();
5057   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5058   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5059     {
5060       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5061       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5062       if(!cm.isQuadratic())
5063         {
5064           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5065           if(typ2==INTERP_KERNEL::NORM_ERROR)
5066             {
5067               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5068               throw INTERP_KERNEL::Exception(oss.str().c_str());
5069             }
5070           types.insert(typ2); newConn->pushBackSilent(typ2);
5071           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5072           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5073             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5074           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5075             {
5076               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5077               int tmpPos=newConn->getNumberOfTuples();
5078               newConn->pushBackSilent(nodeId2);
5079               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5080             }
5081           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5082           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5083           newConnI->pushBackSilent(lastVal);
5084           ret->pushBackSilent(i);
5085         }
5086       else
5087         {
5088           types.insert(typ);
5089           lastVal+=(icPtr[1]-icPtr[0]);
5090           newConnI->pushBackSilent(lastVal);
5091           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5092         }
5093     }
5094   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5095   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5096   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5097   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5098   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5099   int *c=newConn->getPointer();
5100   const int *cI(newConnI->begin());
5101   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5102     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5103   offset=coordsTmp2Safe->getNumberOfTuples();
5104   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5105     c[cI[(*elt)+1]-1]+=offset;
5106   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5107   return ret.retn();
5108 }
5109
5110 /*!
5111  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5112  * so that the number of cells remains the same. Quadratic faces are converted to
5113  * polygons. This method works only for 2D meshes in
5114  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5115  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5116  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5117  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5118  *         a polylinized edge constituting the input polygon.
5119  *  \throw If the coordinates array is not set.
5120  *  \throw If the nodal connectivity of cells is not defined.
5121  *  \throw If \a this->getMeshDimension() != 2.
5122  *  \throw If \a this->getSpaceDimension() != 2.
5123  */
5124 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5125 {
5126   checkFullyDefined();
5127   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5128     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5129   double epsa=fabs(eps);
5130   if(epsa<std::numeric_limits<double>::min())
5131     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 !");
5132   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5133   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5134   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5135   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5136   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5137   revDesc1=0; revDescIndx1=0;
5138   mDesc->tessellate2DCurve(eps);
5139   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5140   setCoords(mDesc->getCoords());
5141 }
5142
5143 /*!
5144  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5145  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5146  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5147  *         a sub-divided edge.
5148  *  \throw If the coordinates array is not set.
5149  *  \throw If the nodal connectivity of cells is not defined.
5150  *  \throw If \a this->getMeshDimension() != 1.
5151  *  \throw If \a this->getSpaceDimension() != 2.
5152  */
5153 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5154 {
5155   checkFullyDefined();
5156   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5157     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5158   double epsa=fabs(eps);
5159   if(epsa<std::numeric_limits<double>::min())
5160     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 !");
5161   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5162   int nbCells=getNumberOfCells();
5163   int nbNodes=getNumberOfNodes();
5164   const int *conn=_nodal_connec->getConstPointer();
5165   const int *connI=_nodal_connec_index->getConstPointer();
5166   const double *coords=_coords->getConstPointer();
5167   std::vector<double> addCoo;
5168   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5169   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5170   newConnI->alloc(nbCells+1,1);
5171   int *newConnIPtr=newConnI->getPointer();
5172   *newConnIPtr=0;
5173   int tmp1[3];
5174   INTERP_KERNEL::Node *tmp2[3];
5175   std::set<INTERP_KERNEL::NormalizedCellType> types;
5176   for(int i=0;i<nbCells;i++,newConnIPtr++)
5177     {
5178       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5179       if(cm.isQuadratic())
5180         {//assert(connI[i+1]-connI[i]-1==3)
5181           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5182           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5183           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5184           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5185           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5186           if(eac)
5187             {
5188               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5189               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5190               delete eac;
5191               newConnIPtr[1]=(int)newConn.size();
5192             }
5193           else
5194             {
5195               types.insert(INTERP_KERNEL::NORM_SEG2);
5196               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5197               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5198               newConnIPtr[1]=newConnIPtr[0]+3;
5199             }
5200         }
5201       else
5202         {
5203           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5204           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5205           newConnIPtr[1]=newConnIPtr[0]+3;
5206         }
5207     }
5208   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5209     return ;
5210   _types=types;
5211   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5212   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5213   newConnArr->alloc((int)newConn.size(),1);
5214   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5215   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5216   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5217   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5218   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5219   std::copy(addCoo.begin(),addCoo.end(),work);
5220   DataArrayDouble::SetArrayIn(newCoords,_coords);
5221   updateTime();
5222 }
5223
5224 /*!
5225  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5226  * In addition, returns an array mapping new cells to old ones. <br>
5227  * This method typically increases the number of cells in \a this mesh
5228  * but the number of nodes remains \b unchanged.
5229  * That's why the 3D splitting policies
5230  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5231  *  \param [in] policy - specifies a pattern used for splitting.
5232  * The semantic of \a policy is:
5233  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5234  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5235  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5236  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5237  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5238  *          an id of old cell producing it. The caller is to delete this array using
5239  *         decrRef() as it is no more needed. 
5240  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5241  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5242  *          and \a this->getMeshDimension() != 3. 
5243  *  \throw If \a policy is not one of the four discussed above.
5244  *  \throw If the nodal connectivity of cells is not defined.
5245  */
5246 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5247 {
5248   switch(policy)
5249     {
5250     case 0:
5251       return simplexizePol0();
5252     case 1:
5253       return simplexizePol1();
5254     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5255       return simplexizePlanarFace5();
5256     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5257       return simplexizePlanarFace6();
5258     default:
5259       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)");
5260     }
5261 }
5262
5263 /*!
5264  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5265  * - 1D: INTERP_KERNEL::NORM_SEG2
5266  * - 2D: INTERP_KERNEL::NORM_TRI3
5267  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5268  *
5269  * This method is useful for users that need to use P1 field services as
5270  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5271  * All these methods need mesh support containing only simplex cells.
5272  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5273  *  \throw If the coordinates array is not set.
5274  *  \throw If the nodal connectivity of cells is not defined.
5275  *  \throw If \a this->getMeshDimension() < 1.
5276  */
5277 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5278 {
5279   checkFullyDefined();
5280   int mdim=getMeshDimension();
5281   if(mdim<1 || mdim>3)
5282     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5283   int nbCells=getNumberOfCells();
5284   const int *conn=_nodal_connec->getConstPointer();
5285   const int *connI=_nodal_connec_index->getConstPointer();
5286   for(int i=0;i<nbCells;i++)
5287     {
5288       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5289       if(!cm.isSimplex())
5290         return false;
5291     }
5292   return true;
5293 }
5294
5295 /*!
5296  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5297  */
5298 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5299 {
5300   checkConnectivityFullyDefined();
5301   if(getMeshDimension()!=2)
5302     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5303   int nbOfCells=getNumberOfCells();
5304   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5305   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5306   ret->alloc(nbOfCells+nbOfCutCells,1);
5307   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5308   int *retPt=ret->getPointer();
5309   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5310   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5311   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5312   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5313   int *pt=newConn->getPointer();
5314   int *ptI=newConnI->getPointer();
5315   ptI[0]=0;
5316   const int *oldc=_nodal_connec->getConstPointer();
5317   const int *ci=_nodal_connec_index->getConstPointer();
5318   for(int i=0;i<nbOfCells;i++,ci++)
5319     {
5320       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5321         {
5322           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5323                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5324           pt=std::copy(tmp,tmp+8,pt);
5325           ptI[1]=ptI[0]+4;
5326           ptI[2]=ptI[0]+8;
5327           *retPt++=i;
5328           *retPt++=i;
5329           ptI+=2;
5330         }
5331       else
5332         {
5333           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5334           ptI[1]=ptI[0]+ci[1]-ci[0];
5335           ptI++;
5336           *retPt++=i;
5337         }
5338     }
5339   _nodal_connec->decrRef();
5340   _nodal_connec=newConn.retn();
5341   _nodal_connec_index->decrRef();
5342   _nodal_connec_index=newConnI.retn();
5343   computeTypes();
5344   updateTime();
5345   return ret.retn();
5346 }
5347
5348 /*!
5349  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5350  */
5351 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5352 {
5353   checkConnectivityFullyDefined();
5354   if(getMeshDimension()!=2)
5355     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5356   int nbOfCells=getNumberOfCells();
5357   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5358   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5359   ret->alloc(nbOfCells+nbOfCutCells,1);
5360   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5361   int *retPt=ret->getPointer();
5362   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5363   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5364   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5365   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5366   int *pt=newConn->getPointer();
5367   int *ptI=newConnI->getPointer();
5368   ptI[0]=0;
5369   const int *oldc=_nodal_connec->getConstPointer();
5370   const int *ci=_nodal_connec_index->getConstPointer();
5371   for(int i=0;i<nbOfCells;i++,ci++)
5372     {
5373       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5374         {
5375           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5376                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5377           pt=std::copy(tmp,tmp+8,pt);
5378           ptI[1]=ptI[0]+4;
5379           ptI[2]=ptI[0]+8;
5380           *retPt++=i;
5381           *retPt++=i;
5382           ptI+=2;
5383         }
5384       else
5385         {
5386           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5387           ptI[1]=ptI[0]+ci[1]-ci[0];
5388           ptI++;
5389           *retPt++=i;
5390         }
5391     }
5392   _nodal_connec->decrRef();
5393   _nodal_connec=newConn.retn();
5394   _nodal_connec_index->decrRef();
5395   _nodal_connec_index=newConnI.retn();
5396   computeTypes();
5397   updateTime();
5398   return ret.retn();
5399 }
5400
5401 /*!
5402  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5403  */
5404 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5405 {
5406   checkConnectivityFullyDefined();
5407   if(getMeshDimension()!=3)
5408     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5409   int nbOfCells=getNumberOfCells();
5410   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5411   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5412   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5413   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5414   int *retPt=ret->getPointer();
5415   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5416   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5417   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5418   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5419   int *pt=newConn->getPointer();
5420   int *ptI=newConnI->getPointer();
5421   ptI[0]=0;
5422   const int *oldc=_nodal_connec->getConstPointer();
5423   const int *ci=_nodal_connec_index->getConstPointer();
5424   for(int i=0;i<nbOfCells;i++,ci++)
5425     {
5426       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5427         {
5428           for(int j=0;j<5;j++,pt+=5,ptI++)
5429             {
5430               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5431               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];
5432               *retPt++=i;
5433               ptI[1]=ptI[0]+5;
5434             }
5435         }
5436       else
5437         {
5438           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5439           ptI[1]=ptI[0]+ci[1]-ci[0];
5440           ptI++;
5441           *retPt++=i;
5442         }
5443     }
5444   _nodal_connec->decrRef();
5445   _nodal_connec=newConn.retn();
5446   _nodal_connec_index->decrRef();
5447   _nodal_connec_index=newConnI.retn();
5448   computeTypes();
5449   updateTime();
5450   return ret.retn();
5451 }
5452
5453 /*!
5454  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5455  */
5456 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5457 {
5458   checkConnectivityFullyDefined();
5459   if(getMeshDimension()!=3)
5460     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5461   int nbOfCells=getNumberOfCells();
5462   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5463   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5464   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5465   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5466   int *retPt=ret->getPointer();
5467   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5468   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5469   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5470   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5471   int *pt=newConn->getPointer();
5472   int *ptI=newConnI->getPointer();
5473   ptI[0]=0;
5474   const int *oldc=_nodal_connec->getConstPointer();
5475   const int *ci=_nodal_connec_index->getConstPointer();
5476   for(int i=0;i<nbOfCells;i++,ci++)
5477     {
5478       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5479         {
5480           for(int j=0;j<6;j++,pt+=5,ptI++)
5481             {
5482               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5483               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];
5484               *retPt++=i;
5485               ptI[1]=ptI[0]+5;
5486             }
5487         }
5488       else
5489         {
5490           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5491           ptI[1]=ptI[0]+ci[1]-ci[0];
5492           ptI++;
5493           *retPt++=i;
5494         }
5495     }
5496   _nodal_connec->decrRef();
5497   _nodal_connec=newConn.retn();
5498   _nodal_connec_index->decrRef();
5499   _nodal_connec_index=newConnI.retn();
5500   computeTypes();
5501   updateTime();
5502   return ret.retn();
5503 }
5504
5505 /*!
5506  * 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.
5507  * This method completly ignore coordinates.
5508  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5509  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5510  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5511  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5512  */
5513 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5514 {
5515   checkFullyDefined();
5516   if(getMeshDimension()!=2)
5517     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5518   int nbOfCells=getNumberOfCells();
5519   int *connI=_nodal_connec_index->getPointer();
5520   int newConnLgth=0;
5521   for(int i=0;i<nbOfCells;i++,connI++)
5522     {
5523       int offset=descIndex[i];
5524       int nbOfEdges=descIndex[i+1]-offset;
5525       //
5526       bool ddirect=desc[offset+nbOfEdges-1]>0;
5527       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5528       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5529       for(int j=0;j<nbOfEdges;j++)
5530         {
5531           bool direct=desc[offset+j]>0;
5532           int edgeId=std::abs(desc[offset+j])-1;
5533           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5534             {
5535               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5536               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5537               int ref2=direct?id1:id2;
5538               if(ref==ref2)
5539                 {
5540                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5541                   newConnLgth+=nbOfSubNodes-1;
5542                   ref=direct?id2:id1;
5543                 }
5544               else
5545                 {
5546                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5547                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5548                 }
5549             }
5550           else
5551             {
5552               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5553             }
5554         }
5555       newConnLgth++;//+1 is for cell type
5556       connI[1]=newConnLgth;
5557     }
5558   //
5559   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5560   newConn->alloc(newConnLgth,1);
5561   int *work=newConn->getPointer();
5562   for(int i=0;i<nbOfCells;i++)
5563     {
5564       *work++=INTERP_KERNEL::NORM_POLYGON;
5565       int offset=descIndex[i];
5566       int nbOfEdges=descIndex[i+1]-offset;
5567       for(int j=0;j<nbOfEdges;j++)
5568         {
5569           bool direct=desc[offset+j]>0;
5570           int edgeId=std::abs(desc[offset+j])-1;
5571           if(direct)
5572             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5573           else
5574             {
5575               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5576               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5577               work=std::copy(it,it+nbOfSubNodes-1,work);
5578             }
5579         }
5580     }
5581   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5582   _types.clear();
5583   if(nbOfCells>0)
5584     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5585 }
5586
5587 /*!
5588  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5589  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5590  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5591  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5592  * so it can be useful to call mergeNodes() before calling this method.
5593  *  \throw If \a this->getMeshDimension() <= 1.
5594  *  \throw If the coordinates array is not set.
5595  *  \throw If the nodal connectivity of cells is not defined.
5596  */
5597 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5598 {
5599   checkFullyDefined();
5600   if(getMeshDimension()<=1)
5601     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5602   int nbOfCells=getNumberOfCells();
5603   if(nbOfCells<1)
5604     return ;
5605   int initMeshLgth=getMeshLength();
5606   int *conn=_nodal_connec->getPointer();
5607   int *index=_nodal_connec_index->getPointer();
5608   int posOfCurCell=0;
5609   int newPos=0;
5610   int lgthOfCurCell;
5611   for(int i=0;i<nbOfCells;i++)
5612     {
5613       lgthOfCurCell=index[i+1]-posOfCurCell;
5614       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5615       int newLgth;
5616       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5617                                                                                                      conn+newPos+1,newLgth);
5618       conn[newPos]=newType;
5619       newPos+=newLgth+1;
5620       posOfCurCell=index[i+1];
5621       index[i+1]=newPos;
5622     }
5623   if(newPos!=initMeshLgth)
5624     _nodal_connec->reAlloc(newPos);
5625   computeTypes();
5626 }
5627
5628 /*!
5629  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5630  * A cell is considered to be oriented correctly if an angle between its
5631  * normal vector and a given vector is less than \c PI / \c 2.
5632  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5633  *         cells. 
5634  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5635  *         checked.
5636  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5637  *         is not cleared before filling in.
5638  *  \throw If \a this->getMeshDimension() != 2.
5639  *  \throw If \a this->getSpaceDimension() != 3.
5640  *
5641  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5642  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5643  */
5644 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5645 {
5646   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5647     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5648   int nbOfCells=getNumberOfCells();
5649   const int *conn=_nodal_connec->getConstPointer();
5650   const int *connI=_nodal_connec_index->getConstPointer();
5651   const double *coordsPtr=_coords->getConstPointer();
5652   for(int i=0;i<nbOfCells;i++)
5653     {
5654       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5655       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5656         {
5657           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5658           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5659             cells.push_back(i);
5660         }
5661     }
5662 }
5663
5664 /*!
5665  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5666  * considered to be oriented correctly if an angle between its normal vector and a
5667  * given vector is less than \c PI / \c 2. 
5668  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5669  *         cells. 
5670  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5671  *         checked.
5672  *  \throw If \a this->getMeshDimension() != 2.
5673  *  \throw If \a this->getSpaceDimension() != 3.
5674  *
5675  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5676  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5677  */
5678 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5679 {
5680   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5681     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5682   int nbOfCells=getNumberOfCells();
5683   int *conn=_nodal_connec->getPointer();
5684   const int *connI=_nodal_connec_index->getConstPointer();
5685   const double *coordsPtr=_coords->getConstPointer();
5686   bool isModified=false;
5687   for(int i=0;i<nbOfCells;i++)
5688     {
5689       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5690       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5691         {
5692           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5693           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5694             {
5695               isModified=true;
5696               std::vector<int> tmp(connI[i+1]-connI[i]-2);
5697               std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5698               std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5699             }
5700         }
5701     }
5702   if(isModified)
5703     _nodal_connec->declareAsNew();
5704   updateTime();
5705 }
5706
5707 /*!
5708  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5709  * oriented facets. The normal vector of the facet should point out of the cell.
5710  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5711  *         is not cleared before filling in.
5712  *  \throw If \a this->getMeshDimension() != 3.
5713  *  \throw If \a this->getSpaceDimension() != 3.
5714  *  \throw If the coordinates array is not set.
5715  *  \throw If the nodal connectivity of cells is not defined.
5716  *
5717  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5718  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5719  */
5720 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5721 {
5722   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5723     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5724   int nbOfCells=getNumberOfCells();
5725   const int *conn=_nodal_connec->getConstPointer();
5726   const int *connI=_nodal_connec_index->getConstPointer();
5727   const double *coordsPtr=_coords->getConstPointer();
5728   for(int i=0;i<nbOfCells;i++)
5729     {
5730       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5731       if(type==INTERP_KERNEL::NORM_POLYHED)
5732         {
5733           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5734             cells.push_back(i);
5735         }
5736     }
5737 }
5738
5739 /*!
5740  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5741  * out of the cell. 
5742  *  \throw If \a this->getMeshDimension() != 3.
5743  *  \throw If \a this->getSpaceDimension() != 3.
5744  *  \throw If the coordinates array is not set.
5745  *  \throw If the nodal connectivity of cells is not defined.
5746  *  \throw If the reparation fails.
5747  *
5748  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5749  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5750  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5751  */
5752 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5753 {
5754   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5755     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5756   int nbOfCells=getNumberOfCells();
5757   int *conn=_nodal_connec->getPointer();
5758   const int *connI=_nodal_connec_index->getConstPointer();
5759   const double *coordsPtr=_coords->getConstPointer();
5760   for(int i=0;i<nbOfCells;i++)
5761     {
5762       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5763       if(type==INTERP_KERNEL::NORM_POLYHED)
5764         {
5765           try
5766             {
5767               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5768                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5769             }
5770           catch(INTERP_KERNEL::Exception& e)
5771             {
5772               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5773               throw INTERP_KERNEL::Exception(oss.str().c_str());
5774             }
5775         }
5776     }
5777   updateTime();
5778 }
5779
5780 /*!
5781  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5782  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5783  * according to which the first facet of the cell should be oriented to have the normal vector
5784  * pointing out of cell.
5785  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5786  *         cells. The caller is to delete this array using decrRef() as it is no more
5787  *         needed. 
5788  *  \throw If \a this->getMeshDimension() != 3.
5789  *  \throw If \a this->getSpaceDimension() != 3.
5790  *  \throw If the coordinates array is not set.
5791  *  \throw If the nodal connectivity of cells is not defined.
5792  *
5793  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5794  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5795  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5796  */
5797 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5798 {
5799   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5800   if(getMeshDimension()!=3)
5801     throw INTERP_KERNEL::Exception(msg);
5802   int spaceDim=getSpaceDimension();
5803   if(spaceDim!=3)
5804     throw INTERP_KERNEL::Exception(msg);
5805   //
5806   int nbOfCells=getNumberOfCells();
5807   int *conn=_nodal_connec->getPointer();
5808   const int *connI=_nodal_connec_index->getConstPointer();
5809   const double *coo=getCoords()->getConstPointer();
5810   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5811   for(int i=0;i<nbOfCells;i++)
5812     {
5813       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5814       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5815         {
5816           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5817             {
5818               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5819               cells->pushBackSilent(i);
5820             }
5821         }
5822     }
5823   return cells.retn();
5824 }
5825
5826 /*!
5827  * This method is a faster method to correct orientation of all 3D cells in \a this.
5828  * 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.
5829  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5830  * 
5831  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5832  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5833  */
5834 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5835 {
5836   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5837     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5838   int nbOfCells=getNumberOfCells();
5839   int *conn=_nodal_connec->getPointer();
5840   const int *connI=_nodal_connec_index->getConstPointer();
5841   const double *coordsPtr=_coords->getConstPointer();
5842   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5843   for(int i=0;i<nbOfCells;i++)
5844     {
5845       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5846       switch(type)
5847         {
5848         case INTERP_KERNEL::NORM_TETRA4:
5849           {
5850             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5851               {
5852                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5853                 ret->pushBackSilent(i);
5854               }
5855             break;
5856           }
5857         case INTERP_KERNEL::NORM_PYRA5:
5858           {
5859             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5860               {
5861                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5862                 ret->pushBackSilent(i);
5863               }
5864             break;
5865           }
5866         case INTERP_KERNEL::NORM_PENTA6:
5867         case INTERP_KERNEL::NORM_HEXA8:
5868         case INTERP_KERNEL::NORM_HEXGP12:
5869           {
5870             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5871               {
5872                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5873                 ret->pushBackSilent(i);
5874               }
5875             break;
5876           }
5877         case INTERP_KERNEL::NORM_POLYHED:
5878           {
5879             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5880               {
5881                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5882                 ret->pushBackSilent(i);
5883               }
5884             break;
5885           }
5886         default:
5887           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 !");
5888         }
5889     }
5890   updateTime();
5891   return ret.retn();
5892 }
5893
5894 /*!
5895  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5896  * If it is not the case an exception will be thrown.
5897  * This method is fast because the first cell of \a this is used to compute the plane.
5898  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5899  * \param pos output of size at least 3 used to store a point owned of searched plane.
5900  */
5901 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5902 {
5903   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5904     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5905   const int *conn=_nodal_connec->getConstPointer();
5906   const int *connI=_nodal_connec_index->getConstPointer();
5907   const double *coordsPtr=_coords->getConstPointer();
5908   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5909   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5910 }
5911
5912 /*!
5913  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5914  * cells. Currently cells of the following types are treated:
5915  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5916  * For a cell of other type an exception is thrown.
5917  * Space dimension of a 2D mesh can be either 2 or 3.
5918  * The Edge Ratio of a cell \f$t\f$ is: 
5919  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5920  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5921  *  the smallest edge lengths of \f$t\f$.
5922  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5923  *          cells and one time, lying on \a this mesh. The caller is to delete this
5924  *          field using decrRef() as it is no more needed. 
5925  *  \throw If the coordinates array is not set.
5926  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5927  *  \throw If the connectivity data array has more than one component.
5928  *  \throw If the connectivity data array has a named component.
5929  *  \throw If the connectivity index data array has more than one component.
5930  *  \throw If the connectivity index data array has a named component.
5931  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5932  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5933  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5934  */
5935 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5936 {
5937   checkCoherency();
5938   int spaceDim=getSpaceDimension();
5939   int meshDim=getMeshDimension();
5940   if(spaceDim!=2 && spaceDim!=3)
5941     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5942   if(meshDim!=2 && meshDim!=3)
5943     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5944   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5945   ret->setMesh(this);
5946   int nbOfCells=getNumberOfCells();
5947   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5948   arr->alloc(nbOfCells,1);
5949   double *pt=arr->getPointer();
5950   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5951   const int *conn=_nodal_connec->getConstPointer();
5952   const int *connI=_nodal_connec_index->getConstPointer();
5953   const double *coo=_coords->getConstPointer();
5954   double tmp[12];
5955   for(int i=0;i<nbOfCells;i++,pt++)
5956     {
5957       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5958       switch(t)
5959         {
5960           case INTERP_KERNEL::NORM_TRI3:
5961             {
5962               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5963               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5964               break;
5965             }
5966           case INTERP_KERNEL::NORM_QUAD4:
5967             {
5968               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5969               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5970               break;
5971             }
5972           case INTERP_KERNEL::NORM_TETRA4:
5973             {
5974               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5975               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5976               break;
5977             }
5978         default:
5979           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5980         }
5981       conn+=connI[i+1]-connI[i];
5982     }
5983   ret->setName("EdgeRatio");
5984   ret->synchronizeTimeWithSupport();
5985   return ret.retn();
5986 }
5987
5988 /*!
5989  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5990  * cells. Currently cells of the following types are treated:
5991  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5992  * For a cell of other type an exception is thrown.
5993  * Space dimension of a 2D mesh can be either 2 or 3.
5994  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5995  *          cells and one time, lying on \a this mesh. The caller is to delete this
5996  *          field using decrRef() as it is no more needed. 
5997  *  \throw If the coordinates array is not set.
5998  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5999  *  \throw If the connectivity data array has more than one component.
6000  *  \throw If the connectivity data array has a named component.
6001  *  \throw If the connectivity index data array has more than one component.
6002  *  \throw If the connectivity index data array has a named component.
6003  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6004  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6005  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6006  */
6007 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6008 {
6009   checkCoherency();
6010   int spaceDim=getSpaceDimension();
6011   int meshDim=getMeshDimension();
6012   if(spaceDim!=2 && spaceDim!=3)
6013     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6014   if(meshDim!=2 && meshDim!=3)
6015     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6016   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6017   ret->setMesh(this);
6018   int nbOfCells=getNumberOfCells();
6019   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6020   arr->alloc(nbOfCells,1);
6021   double *pt=arr->getPointer();
6022   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6023   const int *conn=_nodal_connec->getConstPointer();
6024   const int *connI=_nodal_connec_index->getConstPointer();
6025   const double *coo=_coords->getConstPointer();
6026   double tmp[12];
6027   for(int i=0;i<nbOfCells;i++,pt++)
6028     {
6029       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6030       switch(t)
6031         {
6032           case INTERP_KERNEL::NORM_TRI3:
6033             {
6034               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6035               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6036               break;
6037             }
6038           case INTERP_KERNEL::NORM_QUAD4:
6039             {
6040               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6041               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6042               break;
6043             }
6044           case INTERP_KERNEL::NORM_TETRA4:
6045             {
6046               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6047               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6048               break;
6049             }
6050         default:
6051           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6052         }
6053       conn+=connI[i+1]-connI[i];
6054     }
6055   ret->setName("AspectRatio");
6056   ret->synchronizeTimeWithSupport();
6057   return ret.retn();
6058 }
6059
6060 /*!
6061  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6062  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6063  * treated: INTERP_KERNEL::NORM_QUAD4.
6064  * For a cell of other type an exception is thrown.
6065  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6066  *          cells and one time, lying on \a this mesh. The caller is to delete this
6067  *          field using decrRef() as it is no more needed. 
6068  *  \throw If the coordinates array is not set.
6069  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6070  *  \throw If the connectivity data array has more than one component.
6071  *  \throw If the connectivity data array has a named component.
6072  *  \throw If the connectivity index data array has more than one component.
6073  *  \throw If the connectivity index data array has a named component.
6074  *  \throw If \a this->getMeshDimension() != 2.
6075  *  \throw If \a this->getSpaceDimension() != 3.
6076  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6077  */
6078 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6079 {
6080   checkCoherency();
6081   int spaceDim=getSpaceDimension();
6082   int meshDim=getMeshDimension();
6083   if(spaceDim!=3)
6084     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6085   if(meshDim!=2)
6086     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6087   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6088   ret->setMesh(this);
6089   int nbOfCells=getNumberOfCells();
6090   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6091   arr->alloc(nbOfCells,1);
6092   double *pt=arr->getPointer();
6093   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6094   const int *conn=_nodal_connec->getConstPointer();
6095   const int *connI=_nodal_connec_index->getConstPointer();
6096   const double *coo=_coords->getConstPointer();
6097   double tmp[12];
6098   for(int i=0;i<nbOfCells;i++,pt++)
6099     {
6100       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6101       switch(t)
6102         {
6103           case INTERP_KERNEL::NORM_QUAD4:
6104             {
6105               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6106               *pt=INTERP_KERNEL::quadWarp(tmp);
6107               break;
6108             }
6109         default:
6110           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6111         }
6112       conn+=connI[i+1]-connI[i];
6113     }
6114   ret->setName("Warp");
6115   ret->synchronizeTimeWithSupport();
6116   return ret.retn();
6117 }
6118
6119
6120 /*!
6121  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6122  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6123  * treated: INTERP_KERNEL::NORM_QUAD4.
6124  * For a cell of other type an exception is thrown.
6125  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6126  *          cells and one time, lying on \a this mesh. The caller is to delete this
6127  *          field using decrRef() as it is no more needed. 
6128  *  \throw If the coordinates array is not set.
6129  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6130  *  \throw If the connectivity data array has more than one component.
6131  *  \throw If the connectivity data array has a named component.
6132  *  \throw If the connectivity index data array has more than one component.
6133  *  \throw If the connectivity index data array has a named component.
6134  *  \throw If \a this->getMeshDimension() != 2.
6135  *  \throw If \a this->getSpaceDimension() != 3.
6136  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6137  */
6138 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6139 {
6140   checkCoherency();
6141   int spaceDim=getSpaceDimension();
6142   int meshDim=getMeshDimension();
6143   if(spaceDim!=3)
6144     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6145   if(meshDim!=2)
6146     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6147   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6148   ret->setMesh(this);
6149   int nbOfCells=getNumberOfCells();
6150   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6151   arr->alloc(nbOfCells,1);
6152   double *pt=arr->getPointer();
6153   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6154   const int *conn=_nodal_connec->getConstPointer();
6155   const int *connI=_nodal_connec_index->getConstPointer();
6156   const double *coo=_coords->getConstPointer();
6157   double tmp[12];
6158   for(int i=0;i<nbOfCells;i++,pt++)
6159     {
6160       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6161       switch(t)
6162         {
6163           case INTERP_KERNEL::NORM_QUAD4:
6164             {
6165               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6166               *pt=INTERP_KERNEL::quadSkew(tmp);
6167               break;
6168             }
6169         default:
6170           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6171         }
6172       conn+=connI[i+1]-connI[i];
6173     }
6174   ret->setName("Skew");
6175   ret->synchronizeTimeWithSupport();
6176   return ret.retn();
6177 }
6178
6179 /*!
6180  * This method aggregate the bbox of each cell and put it into bbox parameter.
6181  * \param bbox out parameter of size 2*spacedim*nbOfcells.
6182  */
6183 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6184 {
6185   int spaceDim=getSpaceDimension();
6186   int nbOfCells=getNumberOfCells();
6187   bbox.resize(2*nbOfCells*spaceDim);
6188   for(int i=0;i<nbOfCells*spaceDim;i++)
6189     {
6190       bbox[2*i]=std::numeric_limits<double>::max();
6191       bbox[2*i+1]=-std::numeric_limits<double>::max();
6192     }
6193   const double *coordsPtr=_coords->getConstPointer();
6194   const int *conn=_nodal_connec->getConstPointer();
6195   const int *connI=_nodal_connec_index->getConstPointer();
6196   for(int i=0;i<nbOfCells;i++)
6197     {
6198       int offset=connI[i]+1;
6199       int nbOfNodesForCell=connI[i+1]-offset;
6200       for(int j=0;j<nbOfNodesForCell;j++)
6201         {
6202           int nodeId=conn[offset+j];
6203           if(nodeId>=0)
6204             for(int k=0;k<spaceDim;k++)
6205               {
6206                 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6207                 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6208               }
6209         }
6210     }
6211 }
6212
6213 /// @cond INTERNAL
6214
6215 namespace ParaMEDMEMImpl
6216 {
6217   class ConnReader
6218   {
6219   public:
6220     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6221     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6222   private:
6223     const int *_conn;
6224     int _val;
6225   };
6226
6227   class ConnReader2
6228   {
6229   public:
6230     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6231     bool operator() (const int& pos) { return _conn[pos]==_val; }
6232   private:
6233     const int *_conn;
6234     int _val;
6235   };
6236 }
6237
6238 /// @endcond
6239
6240 /*!
6241  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6242  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6243  * \a this is composed in cell types.
6244  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6245  * For every k in [0,n] ret[3*k+2]==0 because it has no sense here. 
6246  * This parameter is kept only for compatibility with other methode listed above.
6247  */
6248 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6249 {
6250   checkConnectivityFullyDefined();
6251   const int *conn=_nodal_connec->getConstPointer();
6252   const int *connI=_nodal_connec_index->getConstPointer();
6253   const int *work=connI;
6254   int nbOfCells=getNumberOfCells();
6255   std::size_t n=getAllTypes().size();
6256   std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
6257   std::set<INTERP_KERNEL::NormalizedCellType> types;
6258   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6259     {
6260       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6261       if(types.find(typ)!=types.end())
6262         {
6263           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6264           oss << " is not contiguous !";
6265           throw INTERP_KERNEL::Exception(oss.str().c_str());
6266         }
6267       types.insert(typ);
6268       ret[3*i]=typ;
6269       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6270       ret[3*i+1]=(int)std::distance(work,work2);
6271       work=work2;
6272     }
6273   return ret;
6274 }
6275
6276 /*!
6277  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6278  * only for types cell, type node is not managed.
6279  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6280  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6281  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6282  * If 2 or more same geometric type is in \a code and exception is thrown too.
6283  *
6284  * This method firstly checks
6285  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6286  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6287  * an exception is thrown too.
6288  * 
6289  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6290  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6291  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6292  */
6293 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6294 {
6295   if(code.empty())
6296     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6297   std::size_t sz=code.size();
6298   std::size_t n=sz/3;
6299   if(sz%3!=0)
6300     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6301   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6302   int nb=0;
6303   for(std::size_t i=0;i<n;i++)
6304     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6305       {
6306         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6307         nb+=code[3*i+1];
6308         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6309           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6310       }
6311   if(types.size()!=n)
6312     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6313   if(idsPerType.empty())
6314     {
6315       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6316         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6317       if(types.size()==_types.size())
6318         return 0;
6319     }
6320   DataArrayInt *ret=DataArrayInt::New();
6321   ret->alloc(nb,1);
6322   int *retPtr=ret->getPointer();
6323   const int *connI=_nodal_connec_index->getConstPointer();
6324   const int *conn=_nodal_connec->getConstPointer();
6325   int nbOfCells=getNumberOfCells();
6326   const int *i=connI;
6327   int kk=0;
6328   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6329     {
6330       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6331       int offset=(int)std::distance(connI,i);
6332       if(code[3*kk+2]==-1)
6333         {
6334           const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6335           std::size_t pos2=std::distance(i,j);
6336           for(std::size_t k=0;k<pos2;k++)
6337             *retPtr++=(int)k+offset;
6338           i=j;
6339         }
6340       else
6341         {
6342           retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
6343                                 retPtr,std::bind2nd(std::plus<int>(),offset));
6344         }
6345     }
6346   return ret;
6347 }
6348
6349 /*!
6350  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6351  * 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.
6352  * 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.
6353  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6354  * 
6355  * \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.
6356  * \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,
6357  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6358  * \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.
6359  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6360  * \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
6361  */
6362 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6363 {
6364   if(!profile)
6365     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6366   if(profile->getNumberOfComponents()!=1)
6367     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6368   checkConnectivityFullyDefined();
6369   const int *conn=_nodal_connec->getConstPointer();
6370   const int *connI=_nodal_connec_index->getConstPointer();
6371   int nbOfCells=getNumberOfCells();
6372   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6373   std::vector<int> typeRangeVals(1);
6374   for(const int *i=connI;i!=connI+nbOfCells;)
6375     {
6376       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6377       if(std::find(types.begin(),types.end(),curType)!=types.end())
6378         {
6379           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6380         }
6381       types.push_back(curType);
6382       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6383       typeRangeVals.push_back((int)std::distance(connI,i));
6384     }
6385   //
6386   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6387   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6389   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6391   //
6392   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6393   code.resize(3*nbOfCastsFinal);
6394   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6395   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6396   for(int i=0;i<nbOfCastsFinal;i++)
6397     {
6398       int castId=castsPresent->getIJ(i,0);
6399       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6400       idsInPflPerType2.push_back(tmp3);
6401       code[3*i]=(int)types[castId];
6402       code[3*i+1]=tmp3->getNumberOfTuples();
6403       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6404       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6405         {
6406           tmp4->copyStringInfoFrom(*profile);
6407           idsPerType2.push_back(tmp4);
6408           code[3*i+2]=(int)idsPerType2.size()-1;
6409         }
6410       else
6411         {
6412           code[3*i+2]=-1;
6413         }
6414     }
6415   std::size_t sz2=idsInPflPerType2.size();
6416   idsInPflPerType.resize(sz2);
6417   for(std::size_t i=0;i<sz2;i++)
6418     {
6419       DataArrayInt *locDa=idsInPflPerType2[i];
6420       locDa->incrRef();
6421       idsInPflPerType[i]=locDa;
6422     }
6423   std::size_t sz=idsPerType2.size();
6424   idsPerType.resize(sz);
6425   for(std::size_t i=0;i<sz;i++)
6426     {
6427       DataArrayInt *locDa=idsPerType2[i];
6428       locDa->incrRef();
6429       idsPerType[i]=locDa;
6430     }
6431 }
6432
6433 /*!
6434  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6435  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6436  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6437  * 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.
6438  */
6439 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6440 {
6441   checkFullyDefined();
6442   nM1LevMesh->checkFullyDefined();
6443   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6444     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6445   if(_coords!=nM1LevMesh->getCoords())
6446     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6447   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6448   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6449   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6450   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6451   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6452   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6453   tmp->setConnectivity(tmp0,tmp1);
6454   tmp->renumberCells(ret0->getConstPointer(),false);
6455   revDesc=tmp->getNodalConnectivity();
6456   revDescIndx=tmp->getNodalConnectivityIndex();
6457   DataArrayInt *ret=0;
6458   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6459     {
6460       int tmp2;
6461       ret->getMaxValue(tmp2);
6462       ret->decrRef();
6463       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6464       throw INTERP_KERNEL::Exception(oss.str().c_str());
6465     }
6466   nM1LevMeshIds=ret;
6467   //
6468   revDesc->incrRef();
6469   revDescIndx->incrRef();
6470   ret1->incrRef();
6471   ret0->incrRef();
6472   meshnM1Old2New=ret0;
6473   return ret1;
6474 }
6475
6476 /*!
6477  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6478  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6479  * in "Old to New" mode.
6480  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6481  *          this array using decrRef() as it is no more needed.
6482  *  \throw If the nodal connectivity of cells is not defined.
6483  */
6484 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6485 {
6486   checkConnectivityFullyDefined();
6487   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6488   renumberCells(ret->getConstPointer(),false);
6489   return ret.retn();
6490 }
6491
6492 /*!
6493  * This methods checks that cells are sorted by their types.
6494  * This method makes asumption (no check) that connectivity is correctly set before calling.
6495  */
6496 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6497 {
6498   checkFullyDefined();
6499   const int *conn=_nodal_connec->getConstPointer();
6500   const int *connI=_nodal_connec_index->getConstPointer();
6501   int nbOfCells=getNumberOfCells();
6502   std::set<INTERP_KERNEL::NormalizedCellType> types;
6503   for(const int *i=connI;i!=connI+nbOfCells;)
6504     {
6505       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6506       if(types.find(curType)!=types.end())
6507         return false;
6508       types.insert(curType);
6509       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6510     }
6511   return true;
6512 }
6513
6514 /*!
6515  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6516  * The geometric type order is specified by MED file.
6517  * 
6518  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6519  */
6520 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6521 {
6522   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6523 }
6524
6525 /*!
6526  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6527  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6528  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6529  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6530  */
6531 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6532 {
6533   checkFullyDefined();
6534   const int *conn=_nodal_connec->getConstPointer();
6535   const int *connI=_nodal_connec_index->getConstPointer();
6536   int nbOfCells=getNumberOfCells();
6537   if(nbOfCells==0)
6538     return true;
6539   int lastPos=-1;
6540   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6541   for(const int *i=connI;i!=connI+nbOfCells;)
6542     {
6543       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6544       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6545       if(isTypeExists!=orderEnd)
6546         {
6547           int pos=(int)std::distance(orderBg,isTypeExists);
6548           if(pos<=lastPos)
6549             return false;
6550           lastPos=pos;
6551           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6552         }
6553       else
6554         {
6555           if(sg.find(curType)==sg.end())
6556             {
6557               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6558               sg.insert(curType);
6559             }
6560           else
6561             return false;
6562         }
6563     }
6564   return true;
6565 }
6566
6567 /*!
6568  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6569  * 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
6570  * 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'.
6571  */
6572 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6573 {
6574   checkConnectivityFullyDefined();
6575   int nbOfCells=getNumberOfCells();
6576   const int *conn=_nodal_connec->getConstPointer();
6577   const int *connI=_nodal_connec_index->getConstPointer();
6578   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6579   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6580   tmpa->alloc(nbOfCells,1);
6581   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6582   tmpb->fillWithZero();
6583   int *tmp=tmpa->getPointer();
6584   int *tmp2=tmpb->getPointer();
6585   for(const int *i=connI;i!=connI+nbOfCells;i++)
6586     {
6587       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6588       if(where!=orderEnd)
6589         {
6590           int pos=(int)std::distance(orderBg,where);
6591           tmp2[pos]++;
6592           tmp[std::distance(connI,i)]=pos;
6593         }
6594       else
6595         {
6596           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6597           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6598           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6599           throw INTERP_KERNEL::Exception(oss.str().c_str());
6600         }
6601     }
6602   nbPerType=tmpb.retn();
6603   return tmpa.retn();
6604 }
6605
6606 /*!
6607  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6608  *
6609  * \return a new object containing the old to new correspondance.
6610  *
6611  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6612  */
6613 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6614 {
6615   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6616 }
6617
6618 /*!
6619  * 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.
6620  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6621  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6622  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6623  */
6624 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6625 {
6626   DataArrayInt *nbPerType=0;
6627   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6628   nbPerType->decrRef();
6629   return tmpa->buildPermArrPerLevel();
6630 }
6631
6632 /*!
6633  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6634  * The number of cells remains unchanged after the call of this method.
6635  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6636  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6637  *
6638  * \return the array giving the correspondance old to new.
6639  */
6640 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6641 {
6642   checkFullyDefined();
6643   computeTypes();
6644   const int *conn=_nodal_connec->getConstPointer();
6645   const int *connI=_nodal_connec_index->getConstPointer();
6646   int nbOfCells=getNumberOfCells();
6647   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6648   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6649     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6650       {
6651         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6652         types.push_back(curType);
6653         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6654       }
6655   DataArrayInt *ret=DataArrayInt::New();
6656   ret->alloc(nbOfCells,1);
6657   int *retPtr=ret->getPointer();
6658   std::fill(retPtr,retPtr+nbOfCells,-1);
6659   int newCellId=0;
6660   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6661     {
6662       for(const int *i=connI;i!=connI+nbOfCells;i++)
6663         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6664           retPtr[std::distance(connI,i)]=newCellId++;
6665     }
6666   renumberCells(retPtr,false);
6667   return ret;
6668 }
6669
6670 /*!
6671  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6672  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6673  * This method makes asumption that connectivity is correctly set before calling.
6674  */
6675 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6676 {
6677   checkFullyDefined();
6678   const int *conn=_nodal_connec->getConstPointer();
6679   const int *connI=_nodal_connec_index->getConstPointer();
6680   int nbOfCells=getNumberOfCells();
6681   std::vector<MEDCouplingUMesh *> ret;
6682   for(const int *i=connI;i!=connI+nbOfCells;)
6683     {
6684       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6685       int beginCellId=(int)std::distance(connI,i);
6686       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6687       int endCellId=(int)std::distance(connI,i);
6688       int sz=endCellId-beginCellId;
6689       int *cells=new int[sz];
6690       for(int j=0;j<sz;j++)
6691         cells[j]=beginCellId+j;
6692       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6693       delete [] cells;
6694       ret.push_back(m);
6695     }
6696   return ret;
6697 }
6698
6699 /*!
6700  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6701  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6702  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6703  *
6704  * \return a newly allocated instance, that the caller must manage.
6705  * \throw If \a this contains more than one geometric type.
6706  * \throw If the nodal connectivity of \a this is not fully defined.
6707  * \throw If the internal data is not coherent.
6708  */
6709 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6710 {
6711   checkConnectivityFullyDefined();
6712     if(_types.size()!=1)
6713     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6714   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6715   int typi=(int)typ;
6716   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6717   ret->setCoords(getCoords());
6718   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6719   if(retC)
6720     {
6721       int nbCells=getNumberOfCells();
6722       int nbNodesPerCell=retC->getNumberOfNodesPerCell();
6723       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6724       int *outPtr=connOut->getPointer();
6725       const int *conn=_nodal_connec->begin();
6726       const int *connI=_nodal_connec_index->begin();
6727       nbNodesPerCell++;
6728       for(int i=0;i<nbCells;i++,connI++)
6729         {
6730           if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6731             outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6732           else
6733             {
6734               std::ostringstream oss; oss << "MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : 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 << ") !";
6735               throw INTERP_KERNEL::Exception(oss.str().c_str());
6736             }
6737         }
6738       retC->setNodalConnectivity(connOut);
6739     }
6740   else
6741     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : not implemented yet for non static geometric type !");
6742   return ret.retn();
6743 }
6744
6745 /*!
6746  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6747  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6748  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6749  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6750  * are not used here to avoid the build of big permutation array.
6751  *
6752  * \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
6753  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6754  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6755  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6756  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6757  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6758  * \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
6759  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6760  */
6761 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6762                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6763                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6764 {
6765   std::vector<const MEDCouplingUMesh *> ms2;
6766   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6767     if(*it)
6768       {
6769         (*it)->checkConnectivityFullyDefined();
6770         ms2.push_back(*it);
6771       }
6772   if(ms2.empty())
6773     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6774   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6775   int meshDim=ms2[0]->getMeshDimension();
6776   std::vector<const MEDCouplingUMesh *> m1ssm;
6777   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6778   //
6779   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6780   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6781   int fake=0,rk=0;
6782   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6783   ret1->alloc(0,1); ret2->alloc(0,1);
6784   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6785     {
6786       if(meshDim!=(*it)->getMeshDimension())
6787         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6788       if(refCoo!=(*it)->getCoords())
6789         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6790       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6791       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6792       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6793       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6794         {
6795           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6796           m1ssmSingleAuto.push_back(singleCell);
6797           m1ssmSingle.push_back(singleCell);
6798           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6799         }
6800     }
6801   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6802   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6803   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6804   for(std::size_t i=0;i<m1ssm.size();i++)
6805     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6806   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6807   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6808   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6809   return ret0.retn();
6810 }
6811
6812 /*!
6813  * This method returns a newly created DataArrayInt instance.
6814  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6815  */
6816 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6817 {
6818   checkFullyDefined();
6819   const int *conn=_nodal_connec->getConstPointer();
6820   const int *connIndex=_nodal_connec_index->getConstPointer();
6821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6822   for(const int *w=begin;w!=end;w++)
6823     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6824       ret->pushBackSilent(*w);
6825   return ret.retn();
6826 }
6827
6828 /*!
6829  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6830  * are in [0:getNumberOfCells())
6831  */
6832 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6833 {
6834   checkFullyDefined();
6835   const int *conn=_nodal_connec->getConstPointer();
6836   const int *connI=_nodal_connec_index->getConstPointer();
6837   int nbOfCells=getNumberOfCells();
6838   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6839   int *tmp=new int[nbOfCells];
6840   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6841     {
6842       int j=0;
6843       for(const int *i=connI;i!=connI+nbOfCells;i++)
6844         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6845           tmp[std::distance(connI,i)]=j++;
6846     }
6847   DataArrayInt *ret=DataArrayInt::New();
6848   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6849   ret->copyStringInfoFrom(*da);
6850   int *retPtr=ret->getPointer();
6851   const int *daPtr=da->getConstPointer();
6852   int nbOfElems=da->getNbOfElems();
6853   for(int k=0;k<nbOfElems;k++)
6854     retPtr[k]=tmp[daPtr[k]];
6855   delete [] tmp;
6856   return ret;
6857 }
6858
6859 /*!
6860  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6861  * This method \b works \b for mesh sorted by type.
6862  * cells whose ids is in 'idsPerGeoType' array.
6863  * This method conserves coords and name of mesh.
6864  */
6865 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6866 {
6867   std::vector<int> code=getDistributionOfTypes();
6868   std::size_t nOfTypesInThis=code.size()/3;
6869   int sz=0,szOfType=0;
6870   for(std::size_t i=0;i<nOfTypesInThis;i++)
6871     {
6872       if(code[3*i]!=type)
6873         sz+=code[3*i+1];
6874       else
6875         szOfType=code[3*i+1];
6876     }
6877   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6878     if(*work<0 || *work>=szOfType)
6879       {
6880         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6881         oss << ". It should be in [0," << szOfType << ") !";
6882         throw INTERP_KERNEL::Exception(oss.str().c_str());
6883       }
6884   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6885   int *idsPtr=idsTokeep->getPointer();
6886   int offset=0;
6887   for(std::size_t i=0;i<nOfTypesInThis;i++)
6888     {
6889       if(code[3*i]!=type)
6890         for(int j=0;j<code[3*i+1];j++)
6891           *idsPtr++=offset+j;
6892       else
6893         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6894       offset+=code[3*i+1];
6895     }
6896   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6897   ret->copyTinyInfoFrom(this);
6898   return ret.retn();
6899 }
6900
6901 /*!
6902  * This method returns a vector of size 'this->getNumberOfCells()'.
6903  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6904  */
6905 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6906 {
6907   int ncell=getNumberOfCells();
6908   std::vector<bool> ret(ncell);
6909   const int *cI=getNodalConnectivityIndex()->getConstPointer();
6910   const int *c=getNodalConnectivity()->getConstPointer();
6911   for(int i=0;i<ncell;i++)
6912     {
6913       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6914       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6915       ret[i]=cm.isQuadratic();
6916     }
6917   return ret;
6918 }
6919
6920 /*!
6921  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6922  */
6923 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6924 {
6925   if(other->getType()!=UNSTRUCTURED)
6926     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6927   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6928   return MergeUMeshes(this,otherC);
6929 }
6930
6931 /*!
6932  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6933  * computed by averaging coordinates of cell nodes, so this method is not a right
6934  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6935  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6936  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6937  *          components. The caller is to delete this array using decrRef() as it is
6938  *          no more needed.
6939  *  \throw If the coordinates array is not set.
6940  *  \throw If the nodal connectivity of cells is not defined.
6941  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6942  */
6943 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6944 {
6945   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6946   int spaceDim=getSpaceDimension();
6947   int nbOfCells=getNumberOfCells();
6948   ret->alloc(nbOfCells,spaceDim);
6949   ret->copyStringInfoFrom(*getCoords());
6950   double *ptToFill=ret->getPointer();
6951   const int *nodal=_nodal_connec->getConstPointer();
6952   const int *nodalI=_nodal_connec_index->getConstPointer();
6953   const double *coor=_coords->getConstPointer();
6954   for(int i=0;i<nbOfCells;i++)
6955     {
6956       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6957       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6958       ptToFill+=spaceDim;
6959     }
6960   return ret.retn();
6961 }
6962
6963 /*!
6964  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
6965  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
6966  * 
6967  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
6968  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
6969  * 
6970  * \sa MEDCouplingUMesh::getBarycenterAndOwner
6971  * \throw If \a this is not fully defined (coordinates and connectivity)
6972  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
6973  */
6974 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
6975 {
6976   checkFullyDefined();
6977   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6978   int spaceDim=getSpaceDimension();
6979   int nbOfCells=getNumberOfCells();
6980   int nbOfNodes=getNumberOfNodes();
6981   ret->alloc(nbOfCells,spaceDim);
6982   double *ptToFill=ret->getPointer();
6983   const int *nodal=_nodal_connec->getConstPointer();
6984   const int *nodalI=_nodal_connec_index->getConstPointer();
6985   const double *coor=_coords->getConstPointer();
6986   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
6987     {
6988       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6989       std::fill(ptToFill,ptToFill+spaceDim,0.);
6990       if(type!=INTERP_KERNEL::NORM_POLYHED)
6991         {
6992           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
6993             {
6994               if(*conn>=0 && *conn<nbOfNodes)
6995                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
6996               else
6997                 {
6998                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
6999                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7000                 }
7001             }
7002           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7003           if(nbOfNodesInCell>0)
7004             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7005           else
7006             {
7007               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7008               throw INTERP_KERNEL::Exception(oss.str().c_str());
7009             }
7010         }
7011       else
7012         {
7013           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7014           s.erase(-1);
7015           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7016             {
7017               if(*it>=0 && *it<nbOfNodes)
7018                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7019               else
7020                 {
7021                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7022                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7023                 }
7024             }
7025           if(!s.empty())
7026             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7027           else
7028             {
7029               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7030               throw INTERP_KERNEL::Exception(oss.str().c_str());
7031             }
7032         }
7033     }
7034   return ret.retn();
7035 }
7036
7037 /*!
7038  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7039  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7040  * are specified via an array of cell ids. 
7041  *  \warning Validity of the specified cell ids is not checked! 
7042  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7043  *  \param [in] begin - an array of cell ids of interest.
7044  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7045  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7046  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7047  *          caller is to delete this array using decrRef() as it is no more needed. 
7048  *  \throw If the coordinates array is not set.
7049  *  \throw If the nodal connectivity of cells is not defined.
7050  *
7051  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7052  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7053  */
7054 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7055 {
7056   DataArrayDouble *ret=DataArrayDouble::New();
7057   int spaceDim=getSpaceDimension();
7058   int nbOfTuple=(int)std::distance(begin,end);
7059   ret->alloc(nbOfTuple,spaceDim);
7060   double *ptToFill=ret->getPointer();
7061   double *tmp=new double[spaceDim];
7062   const int *nodal=_nodal_connec->getConstPointer();
7063   const int *nodalI=_nodal_connec_index->getConstPointer();
7064   const double *coor=_coords->getConstPointer();
7065   for(const int *w=begin;w!=end;w++)
7066     {
7067       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7068       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7069       ptToFill+=spaceDim;
7070     }
7071   delete [] tmp;
7072   return ret;
7073 }
7074
7075 /*!
7076  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7077  * 
7078  */
7079 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7080 {
7081   if(!da)
7082     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7083   da->checkAllocated();
7084   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7085   ret->setCoords(da);
7086   int nbOfTuples=da->getNumberOfTuples();
7087   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7088   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7089   c->alloc(2*nbOfTuples,1);
7090   cI->alloc(nbOfTuples+1,1);
7091   int *cp=c->getPointer();
7092   int *cip=cI->getPointer();
7093   *cip++=0;
7094   for(int i=0;i<nbOfTuples;i++)
7095     {
7096       *cp++=INTERP_KERNEL::NORM_POINT1;
7097       *cp++=i;
7098       *cip++=2*(i+1);
7099     }
7100   ret->setConnectivity(c,cI,true);
7101   return ret.retn();
7102 }
7103 /*!
7104  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7105  * Cells and nodes of
7106  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7107  *  \param [in] mesh1 - the first mesh.
7108  *  \param [in] mesh2 - the second mesh.
7109  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7110  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7111  *          is no more needed.
7112  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7113  *  \throw If the coordinates array is not set in none of the meshes.
7114  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7115  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7116  */
7117 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7118 {
7119   std::vector<const MEDCouplingUMesh *> tmp(2);
7120   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7121   return MergeUMeshes(tmp);
7122 }
7123
7124 /*!
7125  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7126  * Cells and nodes of
7127  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7128  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7129  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7130  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7131  *          is no more needed.
7132  *  \throw If \a a.size() == 0.
7133  *  \throw If \a a[ *i* ] == NULL.
7134  *  \throw If the coordinates array is not set in none of the meshes.
7135  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7136  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7137 */
7138 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7139 {
7140   std::size_t sz=a.size();
7141   if(sz==0)
7142     return MergeUMeshesLL(a);
7143   for(std::size_t ii=0;ii<sz;ii++)
7144     if(!a[ii])
7145       {
7146         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7147         throw INTERP_KERNEL::Exception(oss.str().c_str());
7148       }
7149   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7150   std::vector< const MEDCouplingUMesh * > aa(sz);
7151   int spaceDim=-3;
7152   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7153     {
7154       const MEDCouplingUMesh *cur=a[i];
7155       const DataArrayDouble *coo=cur->getCoords();
7156       if(coo)
7157         spaceDim=coo->getNumberOfComponents();
7158     }
7159   if(spaceDim==-3)
7160     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7161   for(std::size_t i=0;i<sz;i++)
7162     {
7163       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7164       aa[i]=bb[i];
7165     }
7166   return MergeUMeshesLL(aa);
7167 }
7168
7169 /// @cond INTERNAL
7170
7171 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7172 {
7173   if(a.empty())
7174     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7175   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7176   int meshDim=(*it)->getMeshDimension();
7177   int nbOfCells=(*it)->getNumberOfCells();
7178   int meshLgth=(*it++)->getMeshLength();
7179   for(;it!=a.end();it++)
7180     {
7181       if(meshDim!=(*it)->getMeshDimension())
7182         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7183       nbOfCells+=(*it)->getNumberOfCells();
7184       meshLgth+=(*it)->getMeshLength();
7185     }
7186   std::vector<const MEDCouplingPointSet *> aps(a.size());
7187   std::copy(a.begin(),a.end(),aps.begin());
7188   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7189   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7190   ret->setCoords(pts);
7191   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7192   c->alloc(meshLgth,1);
7193   int *cPtr=c->getPointer();
7194   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7195   cI->alloc(nbOfCells+1,1);
7196   int *cIPtr=cI->getPointer();
7197   *cIPtr++=0;
7198   int offset=0;
7199   int offset2=0;
7200   for(it=a.begin();it!=a.end();it++)
7201     {
7202       int curNbOfCell=(*it)->getNumberOfCells();
7203       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7204       const int *curC=(*it)->_nodal_connec->getConstPointer();
7205       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7206       for(int j=0;j<curNbOfCell;j++)
7207         {
7208           const int *src=curC+curCI[j];
7209           *cPtr++=*src++;
7210           for(;src!=curC+curCI[j+1];src++,cPtr++)
7211             {
7212               if(*src!=-1)
7213                 *cPtr=*src+offset2;
7214               else
7215                 *cPtr=-1;
7216             }
7217         }
7218       offset+=curCI[curNbOfCell];
7219       offset2+=(*it)->getNumberOfNodes();
7220     }
7221   //
7222   ret->setConnectivity(c,cI,true);
7223   return ret.retn();
7224 }
7225
7226 /// @endcond
7227
7228 /*!
7229  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7230  * dimension and sharing the node coordinates array.
7231  * All cells of the first mesh precede all cells of the second mesh
7232  * within the result mesh. 
7233  *  \param [in] mesh1 - the first mesh.
7234  *  \param [in] mesh2 - the second mesh.
7235  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7236  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7237  *          is no more needed.
7238  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7239  *  \throw If the meshes do not share the node coordinates array.
7240  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7241  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7242  */
7243 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7244 {
7245   std::vector<const MEDCouplingUMesh *> tmp(2);
7246   tmp[0]=mesh1; tmp[1]=mesh2;
7247   return MergeUMeshesOnSameCoords(tmp);
7248 }
7249
7250 /*!
7251  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7252  * dimension and sharing the node coordinates array.
7253  * All cells of the *i*-th mesh precede all cells of the
7254  * (*i*+1)-th mesh within the result mesh.
7255  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7256  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7257  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7258  *          is no more needed.
7259  *  \throw If \a a.size() == 0.
7260  *  \throw If \a a[ *i* ] == NULL.
7261  *  \throw If the meshes do not share the node coordinates array.
7262  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7263  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7264  */
7265 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7266 {
7267   if(meshes.empty())
7268     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7269   for(std::size_t ii=0;ii<meshes.size();ii++)
7270     if(!meshes[ii])
7271       {
7272         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7273         throw INTERP_KERNEL::Exception(oss.str().c_str());
7274       }
7275   const DataArrayDouble *coords=meshes.front()->getCoords();
7276   int meshDim=meshes.front()->getMeshDimension();
7277   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7278   int meshLgth=0;
7279   int meshIndexLgth=0;
7280   for(;iter!=meshes.end();iter++)
7281     {
7282       if(coords!=(*iter)->getCoords())
7283         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7284       if(meshDim!=(*iter)->getMeshDimension())
7285         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7286       meshLgth+=(*iter)->getMeshLength();
7287       meshIndexLgth+=(*iter)->getNumberOfCells();
7288     }
7289   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7290   nodal->alloc(meshLgth,1);
7291   int *nodalPtr=nodal->getPointer();
7292   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7293   nodalIndex->alloc(meshIndexLgth+1,1);
7294   int *nodalIndexPtr=nodalIndex->getPointer();
7295   int offset=0;
7296   for(iter=meshes.begin();iter!=meshes.end();iter++)
7297     {
7298       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7299       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7300       int nbOfCells=(*iter)->getNumberOfCells();
7301       int meshLgth2=(*iter)->getMeshLength();
7302       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7303       if(iter!=meshes.begin())
7304         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7305       else
7306         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7307       offset+=meshLgth2;
7308     }
7309   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7310   ret->setName("merge");
7311   ret->setMeshDimension(meshDim);
7312   ret->setConnectivity(nodal,nodalIndex,true);
7313   ret->setCoords(coords);
7314   return ret;
7315 }
7316
7317 /*!
7318  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7319  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7320  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7321  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7322  * New" mode are returned for each input mesh.
7323  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7324  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7325  *          valid values [0,1,2], see zipConnectivityTraducer().
7326  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7327  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7328  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7329  *          no more needed.
7330  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7331  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7332  *          is no more needed.
7333  *  \throw If \a meshes.size() == 0.
7334  *  \throw If \a meshes[ *i* ] == NULL.
7335  *  \throw If the meshes do not share the node coordinates array.
7336  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7337  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7338  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7339  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7340  */
7341 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7342 {
7343   //All checks are delegated to MergeUMeshesOnSameCoords
7344   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7345   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7346   corr.resize(meshes.size());
7347   std::size_t nbOfMeshes=meshes.size();
7348   int offset=0;
7349   const int *o2nPtr=o2n->getConstPointer();
7350   for(std::size_t i=0;i<nbOfMeshes;i++)
7351     {
7352       DataArrayInt *tmp=DataArrayInt::New();
7353       int curNbOfCells=meshes[i]->getNumberOfCells();
7354       tmp->alloc(curNbOfCells,1);
7355       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7356       offset+=curNbOfCells;
7357       tmp->setName(meshes[i]->getName());
7358       corr[i]=tmp;
7359     }
7360   return ret.retn();
7361 }
7362
7363 /*!
7364  * Makes all given meshes share the nodal connectivity array. The common connectivity
7365  * array is created by concatenating the connectivity arrays of all given meshes. All
7366  * the given meshes must be of the same space dimension but dimension of cells **can
7367  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7368  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7369  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7370  *  \param [in,out] meshes - a vector of meshes to update.
7371  *  \throw If any of \a meshes is NULL.
7372  *  \throw If the coordinates array is not set in any of \a meshes.
7373  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7374  *  \throw If \a meshes are of different space dimension.
7375  */
7376 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7377 {
7378   std::size_t sz=meshes.size();
7379   if(sz==0 || sz==1)
7380     return;
7381   std::vector< const DataArrayDouble * > coords(meshes.size());
7382   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7383   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7384     {
7385       if((*it))
7386         {
7387           (*it)->checkConnectivityFullyDefined();
7388           const DataArrayDouble *coo=(*it)->getCoords();
7389           if(coo)
7390             *it2=coo;
7391           else
7392             {
7393               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7394               oss << " has no coordinate array defined !";
7395               throw INTERP_KERNEL::Exception(oss.str().c_str());
7396             }
7397         }
7398       else
7399         {
7400           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7401           oss << " is null !";
7402           throw INTERP_KERNEL::Exception(oss.str().c_str());
7403         }
7404     }
7405   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7406   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7407   int offset=(*it)->getNumberOfNodes();
7408   (*it++)->setCoords(res);
7409   for(;it!=meshes.end();it++)
7410     {
7411       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7412       (*it)->setCoords(res);
7413       (*it)->shiftNodeNumbersInConn(offset);
7414       offset+=oldNumberOfNodes;
7415     }
7416 }
7417
7418 /*!
7419  * Merges nodes coincident with a given precision within all given meshes that share
7420  * the nodal connectivity array. The given meshes **can be of different** mesh
7421  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7422  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7423  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7424  *  \param [in,out] meshes - a vector of meshes to update.
7425  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7426  *  \throw If any of \a meshes is NULL.
7427  *  \throw If the \a meshes do not share the same node coordinates array.
7428  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7429  */
7430 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7431 {
7432   if(meshes.empty())
7433     return ;
7434   std::set<const DataArrayDouble *> s;
7435   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7436     {
7437       if(*it)
7438         s.insert((*it)->getCoords());
7439       else
7440         {
7441           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 !";
7442           throw INTERP_KERNEL::Exception(oss.str().c_str());
7443         }
7444     }
7445   if(s.size()!=1)
7446     {
7447       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 !";
7448       throw INTERP_KERNEL::Exception(oss.str().c_str());
7449     }
7450   const DataArrayDouble *coo=*(s.begin());
7451   if(!coo)
7452     return;
7453   //
7454   DataArrayInt *comm,*commI;
7455   coo->findCommonTuples(eps,-1,comm,commI);
7456   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7457   int oldNbOfNodes=coo->getNumberOfTuples();
7458   int newNbOfNodes;
7459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7460   if(oldNbOfNodes==newNbOfNodes)
7461     return ;
7462   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7463   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7464     {
7465       (*it)->renumberNodesInConn(o2n->getConstPointer());
7466       (*it)->setCoords(newCoords);
7467     } 
7468 }
7469
7470 /*!
7471  * 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.
7472  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7473  * \param isQuad specifies the policy of connectivity.
7474  * @ret in/out parameter in which the result will be append
7475  */
7476 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7477 {
7478   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7479   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7480   ret.push_back(cm.getExtrudedType());
7481   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7482   switch(flatType)
7483     {
7484     case INTERP_KERNEL::NORM_POINT1:
7485       {
7486         ret.push_back(connBg[1]);
7487         ret.push_back(connBg[1]+nbOfNodesPerLev);
7488         break;
7489       }
7490     case INTERP_KERNEL::NORM_SEG2:
7491       {
7492         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7493         ret.insert(ret.end(),conn,conn+4);
7494         break;
7495       }
7496     case INTERP_KERNEL::NORM_SEG3:
7497       {
7498         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7499         ret.insert(ret.end(),conn,conn+8);
7500         break;
7501       }
7502     case INTERP_KERNEL::NORM_QUAD4:
7503       {
7504         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7505         ret.insert(ret.end(),conn,conn+8);
7506         break;
7507       }
7508     case INTERP_KERNEL::NORM_TRI3:
7509       {
7510         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7511         ret.insert(ret.end(),conn,conn+6);
7512         break;
7513       }
7514     case INTERP_KERNEL::NORM_TRI6:
7515       {
7516         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,
7517                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7518         ret.insert(ret.end(),conn,conn+15);
7519         break;
7520       }
7521     case INTERP_KERNEL::NORM_QUAD8:
7522       {
7523         int conn[20]={
7524           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7525           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7526           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7527         };
7528         ret.insert(ret.end(),conn,conn+20);
7529         break;
7530       }
7531     case INTERP_KERNEL::NORM_POLYGON:
7532       {
7533         std::back_insert_iterator< std::vector<int> > ii(ret);
7534         std::copy(connBg+1,connEnd,ii);
7535         *ii++=-1;
7536         std::reverse_iterator<const int *> rConnBg(connEnd);
7537         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7538         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7539         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7540         for(std::size_t i=0;i<nbOfRadFaces;i++)
7541           {
7542             *ii++=-1;
7543             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7544             std::copy(conn,conn+4,ii);
7545           }
7546         break;
7547       }
7548     default:
7549       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7550     }
7551 }
7552
7553 /*!
7554  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7555  */
7556 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7557 {
7558   double v[3]={0.,0.,0.};
7559   std::size_t sz=std::distance(begin,end);
7560   if(isQuadratic)
7561     sz/=2;
7562   for(std::size_t i=0;i<sz;i++)
7563     {
7564       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];
7565       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7566       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7567     }
7568   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7569 }
7570
7571 /*!
7572  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7573  */
7574 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7575 {
7576   std::vector<std::pair<int,int> > edges;
7577   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7578   const int *bgFace=begin;
7579   for(std::size_t i=0;i<nbOfFaces;i++)
7580     {
7581       const int *endFace=std::find(bgFace+1,end,-1);
7582       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7583       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7584         {
7585           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7586           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7587             return false;
7588           edges.push_back(p1);
7589         }
7590       bgFace=endFace+1;
7591     }
7592   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7593 }
7594
7595 /*!
7596  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7597  */
7598 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7599 {
7600   double vec0[3],vec1[3];
7601   std::size_t sz=std::distance(begin,end);
7602   if(sz%2!=0)
7603     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7604   int nbOfNodes=(int)sz/2;
7605   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7606   const double *pt0=coords+3*begin[0];
7607   const double *pt1=coords+3*begin[nbOfNodes];
7608   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7609   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7610 }
7611
7612 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7613 {
7614   std::size_t sz=std::distance(begin,end);
7615   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7616   std::size_t nbOfNodes(sz/2);
7617   std::copy(begin,end,(int *)tmp);
7618   for(std::size_t j=1;j<nbOfNodes;j++)
7619     {
7620       begin[j]=tmp[nbOfNodes-j];
7621       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7622     }
7623 }
7624
7625 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7626 {
7627   std::size_t sz=std::distance(begin,end);
7628   if(sz!=4)
7629     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7630   double vec0[3],vec1[3];
7631   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7632   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]; 
7633   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;
7634 }
7635
7636 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7637 {
7638   std::size_t sz=std::distance(begin,end);
7639   if(sz!=5)
7640     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7641   double vec0[3];
7642   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7643   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7644   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7645 }
7646
7647 /*!
7648  * 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 ) 
7649  * 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
7650  * a 2D space.
7651  *
7652  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7653  * \param [in] coords the coordinates with nb of components exactly equal to 3
7654  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7655  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7656  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7657  */
7658 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7659 {
7660   int nbFaces=std::count(begin+1,end,-1)+1;
7661   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7662   double *vPtr=v->getPointer();
7663   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7664   double *pPtr=p->getPointer();
7665   const int *stFaceConn=begin+1;
7666   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7667     {
7668       const int *endFaceConn=std::find(stFaceConn,end,-1);
7669       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7670       stFaceConn=endFaceConn+1;
7671     }
7672   pPtr=p->getPointer(); vPtr=v->getPointer();
7673   DataArrayInt *comm1=0,*commI1=0;
7674   v->findCommonTuples(eps,-1,comm1,commI1);
7675   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7676   const int *comm1Ptr=comm1->getConstPointer();
7677   const int *commI1Ptr=commI1->getConstPointer();
7678   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7679   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7680   //
7681   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7682   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7683   mm->finishInsertingCells();
7684   //
7685   for(int i=0;i<nbOfGrps1;i++)
7686     {
7687       int vecId=comm1Ptr[commI1Ptr[i]];
7688       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7689       DataArrayInt *comm2=0,*commI2=0;
7690       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7691       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7692       const int *comm2Ptr=comm2->getConstPointer();
7693       const int *commI2Ptr=commI2->getConstPointer();
7694       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7695       for(int j=0;j<nbOfGrps2;j++)
7696         {
7697           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7698             {
7699               res->insertAtTheEnd(begin,end);
7700               res->pushBackSilent(-1);
7701             }
7702           else
7703             {
7704               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7705               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7706               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7707               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7708               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7709               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7710               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7711               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7712               const int *idsNodePtr=idsNode->getConstPointer();
7713               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];
7714               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7715               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7716               if(std::abs(norm)>eps)
7717                 {
7718                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7719                   mm3->rotate(center,vec,angle);
7720                 }
7721               mm3->changeSpaceDimension(2);
7722               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7723               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7724               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7725               int nbOfCells=mm4->getNumberOfCells();
7726               for(int k=0;k<nbOfCells;k++)
7727                 {
7728                   int l=0;
7729                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7730                     res->pushBackSilent(idsNodePtr[*work]);
7731                   res->pushBackSilent(-1);
7732                 }
7733             }
7734         }
7735     }
7736   res->popBackSilent();
7737 }
7738
7739 /*!
7740  * 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
7741  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7742  * 
7743  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7744  * \param [in] coords coordinates expected to have 3 components.
7745  * \param [in] begin start of the nodal connectivity of the face.
7746  * \param [in] end end of the nodal connectivity (excluded) of the face.
7747  * \param [out] v the normalized vector of size 3
7748  * \param [out] p the pos of plane
7749  */
7750 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7751 {
7752   std::size_t nbPoints=std::distance(begin,end);
7753   if(nbPoints<3)
7754     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7755   double vec[3]={0.,0.,0.};
7756   std::size_t j=0;
7757   bool refFound=false;
7758   for(;j<nbPoints-1 && !refFound;j++)
7759     {
7760       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7761       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7762       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7763       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7764       if(norm>eps)
7765         {
7766           refFound=true;
7767           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7768         }
7769     }
7770   for(std::size_t i=j;i<nbPoints-1;i++)
7771     {
7772       double curVec[3];
7773       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7774       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7775       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7776       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7777       if(norm<eps)
7778         continue;
7779       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7780       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];
7781       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7782       if(norm>eps)
7783         {
7784           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7785           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7786           return ;
7787         }
7788     }
7789   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7790 }
7791
7792 /*!
7793  * This method tries to obtain a well oriented polyhedron.
7794  * If the algorithm fails, an exception will be thrown.
7795  */
7796 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7797 {
7798   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7799   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7800   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7801   isPerm[0]=true;
7802   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7803   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7804   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7805   //
7806   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7807     {
7808       bgFace=begin;
7809       std::size_t smthChanged=0;
7810       for(std::size_t i=0;i<nbOfFaces;i++)
7811         {
7812           endFace=std::find(bgFace+1,end,-1);
7813           nbOfEdgesInFace=std::distance(bgFace,endFace);
7814           if(!isPerm[i])
7815             {
7816               bool b;
7817               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7818                 {
7819                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7820                   std::pair<int,int> p2(p1.second,p1.first);
7821                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7822                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7823                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7824                 }
7825               if(isPerm[i])
7826                 { 
7827                   if(!b)
7828                     std::reverse(bgFace+1,endFace);
7829                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7830                     {
7831                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7832                       std::pair<int,int> p2(p1.second,p1.first);
7833                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7834                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7835                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7836                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7837                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7838                       if(it!=edgesOK.end())
7839                         {
7840                           edgesOK.erase(it);
7841                           edgesFinished.push_back(p1);
7842                         }
7843                       else
7844                         edgesOK.push_back(p1);
7845                     }
7846                 }
7847             }
7848           bgFace=endFace+1;
7849         }
7850       if(smthChanged==0)
7851         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7852     }
7853   if(!edgesOK.empty())
7854     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7855   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7856     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7857       bgFace=begin;
7858       for(std::size_t i=0;i<nbOfFaces;i++)
7859         {
7860           endFace=std::find(bgFace+1,end,-1);
7861           std::reverse(bgFace+1,endFace);
7862           bgFace=endFace+1;
7863         }
7864     }
7865 }
7866
7867 /*!
7868  * This method makes the assumption spacedimension == meshdimension == 2.
7869  * This method works only for linear cells.
7870  * 
7871  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7872  */
7873 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7874 {
7875   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7876     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7877   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7878   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7879   int nbOfNodesExpected=m->getNumberOfNodes();
7880   if(m->getNumberOfCells()!=nbOfNodesExpected)
7881     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7882   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7883   const int *n2oPtr=n2o->getConstPointer();
7884   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7885   m->getReverseNodalConnectivity(revNodal,revNodalI);
7886   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7887   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7888   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7889   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7890   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
7891   if(nbOfNodesExpected<1)
7892     return ret.retn();
7893   int prevCell=0;
7894   int prevNode=nodalPtr[nodalIPtr[0]+1];
7895   *work++=n2oPtr[prevNode];
7896   for(int i=1;i<nbOfNodesExpected;i++)
7897     {
7898       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7899         {
7900           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7901           conn.erase(prevNode);
7902           if(conn.size()==1)
7903             {
7904               int curNode=*(conn.begin());
7905               *work++=n2oPtr[curNode];
7906               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7907               shar.erase(prevCell);
7908               if(shar.size()==1)
7909                 {
7910                   prevCell=*(shar.begin());
7911                   prevNode=curNode;
7912                 }
7913               else
7914                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
7915             }
7916           else
7917             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
7918         }
7919       else
7920         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
7921     }
7922   return ret.retn();
7923 }
7924
7925 /*!
7926  * This method makes the assumption spacedimension == meshdimension == 3.
7927  * This method works only for linear cells.
7928  * 
7929  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7930  */
7931 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
7932 {
7933   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7934     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7935   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7936   const int *conn=m->getNodalConnectivity()->getConstPointer();
7937   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
7938   int nbOfCells=m->getNumberOfCells();
7939   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7940   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
7941   if(nbOfCells<1)
7942     return ret.retn();
7943   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7944   for(int i=1;i<nbOfCells;i++)
7945     {
7946       *work++=-1;
7947       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7948     }
7949   return ret.retn();
7950 }
7951
7952 /*!
7953  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
7954  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
7955  */
7956 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
7957 {
7958   double *w=zipFrmt;
7959   if(spaceDim==3)
7960     for(int i=0;i<nbOfNodesInCell;i++)
7961       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
7962   else if(spaceDim==2)
7963     {
7964       for(int i=0;i<nbOfNodesInCell;i++)
7965         {
7966           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
7967           *w++=0.;
7968         }
7969     }
7970   else
7971     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
7972 }
7973
7974 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
7975 {
7976   int nbOfCells=getNumberOfCells();
7977   if(nbOfCells<=0)
7978     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7979   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,-1,4};
7980   ofs << "  <" << getVTKDataSetType() << ">\n";
7981   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7982   ofs << "      <PointData>\n" << pointData << std::endl;
7983   ofs << "      </PointData>\n";
7984   ofs << "      <CellData>\n" << cellData << std::endl;
7985   ofs << "      </CellData>\n";
7986   ofs << "      <Points>\n";
7987   if(getSpaceDimension()==3)
7988     _coords->writeVTK(ofs,8,"Points");
7989   else
7990     {
7991       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7992       coo->writeVTK(ofs,8,"Points");
7993     }
7994   ofs << "      </Points>\n";
7995   ofs << "      <Cells>\n";
7996   const int *cPtr=_nodal_connec->getConstPointer();
7997   const int *cIPtr=_nodal_connec_index->getConstPointer();
7998   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
7999   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8001   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8002   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8003   int szFaceOffsets=0,szConn=0;
8004   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8005     {
8006       *w2=cPtr[cIPtr[i]];
8007       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8008         {
8009           *w1=-1;
8010           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8011           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8012         }
8013       else
8014         {
8015           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8016           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8017           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8018           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8019           w4=std::copy(c.begin(),c.end(),w4);
8020         }
8021     }
8022   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8023   types->writeVTK(ofs,8,"UInt8","types");
8024   offsets->writeVTK(ofs,8,"Int32","offsets");
8025   if(szFaceOffsets!=0)
8026     {//presence of Polyhedra
8027       connectivity->reAlloc(szConn);
8028       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8029       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8030       w1=faces->getPointer();
8031       for(int i=0;i<nbOfCells;i++)
8032         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8033           {
8034             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8035             *w1++=nbFaces;
8036             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8037             for(int j=0;j<nbFaces;j++)
8038               {
8039                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8040                 *w1++=(int)std::distance(w6,w5);
8041                 w1=std::copy(w6,w5,w1);
8042                 w6=w5+1;
8043               }
8044           }
8045       faces->writeVTK(ofs,8,"Int32","faces");
8046     }
8047   connectivity->writeVTK(ofs,8,"Int32","connectivity");
8048   ofs << "      </Cells>\n";
8049   ofs << "    </Piece>\n";
8050   ofs << "  </" << getVTKDataSetType() << ">\n";
8051 }
8052
8053 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8054 {
8055   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8056   if(_mesh_dim==-2)
8057     { stream << " Not set !"; return ; }
8058   stream << " Mesh dimension : " << _mesh_dim << ".";
8059   if(_mesh_dim==-1)
8060     return ;
8061   if(!_coords)
8062     { stream << " No coordinates set !"; return ; }
8063   if(!_coords->isAllocated())
8064     { stream << " Coordinates set but not allocated !"; return ; }
8065   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8066   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8067   if(!_nodal_connec_index)
8068     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8069   if(!_nodal_connec_index->isAllocated())
8070     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8071   int lgth=_nodal_connec_index->getNumberOfTuples();
8072   int cpt=_nodal_connec_index->getNumberOfComponents();
8073   if(cpt!=1 || lgth<1)
8074     return ;
8075   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8076 }
8077
8078 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8079 {
8080   return std::string("UnstructuredGrid");
8081 }
8082
8083 /*!
8084  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8085  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8086  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8087  * meshes.
8088  *  \param [in] m1 - the first input mesh which is a partitioned object.
8089  *  \param [in] m2 - the second input mesh which is a partition tool.
8090  *  \param [in] eps - precision used to detect coincident mesh entities.
8091  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8092  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8093  *         this array using decrRef() as it is no more needed.
8094  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8095  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8096  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8097  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8098  *         it is no more needed.  
8099  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8100  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8101  *         is no more needed.  
8102  *  \throw If the coordinates array is not set in any of the meshes.
8103  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8104  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8105  */
8106 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8107 {
8108   m1->checkFullyDefined();
8109   m2->checkFullyDefined();
8110   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8112   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8113   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8114   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8115   std::vector<double> addCoo,addCoordsQuadratic;
8116   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8117   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8118   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8119                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8120   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8121   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8122   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8123   std::vector< std::vector<int> > intersectEdge2;
8124   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8125   subDiv2.clear(); dd5=0; dd6=0;
8126   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8127   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8128   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8129                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8130   //
8131   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8132   addCooDa->alloc((int)(addCoo.size())/2,2);
8133   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8134   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8135   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8136   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8137   std::vector<const DataArrayDouble *> coordss(4);
8138   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8139   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8140   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8141   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8142   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8143   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8144   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8145   ret->setConnectivity(conn,connI,true);
8146   ret->setCoords(coo);
8147   cellNb1=c1.retn(); cellNb2=c2.retn();
8148   return ret.retn();
8149 }
8150
8151 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8152                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8153                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8154                                                          const std::vector<double>& addCoords,
8155                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8156 {
8157   static const int SPACEDIM=2;
8158   std::vector<double> bbox1,bbox2;
8159   const double *coo1=m1->getCoords()->getConstPointer();
8160   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8161   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8162   int offset1=m1->getNumberOfNodes();
8163   const double *coo2=m2->getCoords()->getConstPointer();
8164   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8165   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8166   int offset2=offset1+m2->getNumberOfNodes();
8167   int offset3=offset2+((int)addCoords.size())/2;
8168   m1->getBoundingBoxForBBTree(bbox1);
8169   m2->getBoundingBoxForBBTree(bbox2);
8170   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8171   int ncell1=m1->getNumberOfCells();
8172   crI.push_back(0);
8173   for(int i=0;i<ncell1;i++)
8174     {
8175       std::vector<int> candidates2;
8176       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8177       std::map<INTERP_KERNEL::Node *,int> mapp;
8178       std::map<int,INTERP_KERNEL::Node *> mappRev;
8179       INTERP_KERNEL::QuadraticPolygon pol1;
8180       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8181       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8182       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8183       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8184                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8185       //
8186       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
8187       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8188       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8189       for(it1.first();!it1.finished();it1.next())
8190         edges1.insert(it1.current()->getPtr());
8191       //
8192       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8193       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8194       int ii=0;
8195       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8196         {
8197           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8198           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8199           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8200           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8201                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8202         }
8203       ii=0;
8204       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8205         {
8206           pol1.initLocationsWithOther(pol2s[ii]);
8207           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8208           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8209           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8210         }
8211       if(!edges1.empty())
8212         {
8213           try
8214             {
8215               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8216             }
8217           catch(INTERP_KERNEL::Exception& e)
8218             {
8219               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();
8220               throw INTERP_KERNEL::Exception(oss.str().c_str());
8221             }
8222         }
8223       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8224         (*it).second->decrRef();
8225     }
8226 }
8227
8228 /*!
8229  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8230  * 
8231  */
8232 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8233                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8234                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8235                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8236                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8237 {
8238   static const int SPACEDIM=2;
8239   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8240   desc2=DataArrayInt::New();
8241   descIndx2=DataArrayInt::New();
8242   revDesc2=DataArrayInt::New();
8243   revDescIndx2=DataArrayInt::New();
8244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8245   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8246   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8247   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8248   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8249   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8250   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8251   std::vector<double> bbox1,bbox2;
8252   m1Desc->getBoundingBoxForBBTree(bbox1);
8253   m2Desc->getBoundingBoxForBBTree(bbox2);
8254   int ncell1=m1Desc->getNumberOfCells();
8255   int ncell2=m2Desc->getNumberOfCells();
8256   intersectEdge1.resize(ncell1);
8257   colinear2.resize(ncell2);
8258   subDiv2.resize(ncell2);
8259   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8260   std::vector<int> candidates1(1);
8261   int offset1=m1->getNumberOfNodes();
8262   int offset2=offset1+m2->getNumberOfNodes();
8263   for(int i=0;i<ncell1;i++)
8264     {
8265       std::vector<int> candidates2;
8266       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8267       if(!candidates2.empty())
8268         {
8269           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8270           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8271           candidates1[0]=i;
8272           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8273           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8274           delete pol2;
8275           delete pol1;
8276         }
8277       else
8278         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8279     }
8280   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8281   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8282 }
8283
8284 /*!
8285  * This method performs the 2nd step of Partition of 2D mesh.
8286  * This method has 4 inputs :
8287  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8288  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8289  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8290  * The aim of this method is to sort the splitting nodes, if any, and to put in 'intersectEdge' output paramter based on edges of mesh 'm2'
8291  * \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. Only present for its coords in case of 'subDiv' shares some nodes of 'm1'
8292  * \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.
8293  * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8294  */
8295 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, const std::vector<double>& addCoo, const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge) throw(INTERP_KERNEL::Exception)
8296 {
8297   int offset1=m1->getNumberOfNodes();
8298   int ncell=m2->getNumberOfCells();
8299   const int *c=m2->getNodalConnectivity()->getConstPointer();
8300   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8301   const double *coo=m2->getCoords()->getConstPointer();
8302   const double *cooBis=m1->getCoords()->getConstPointer();
8303   int offset2=offset1+m2->getNumberOfNodes();
8304   intersectEdge.resize(ncell);
8305   for(int i=0;i<ncell;i++,cI++)
8306     {
8307       const std::vector<int>& divs=subDiv[i];
8308       int nnode=cI[1]-cI[0]-1;
8309       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8310       std::map<INTERP_KERNEL::Node *, int> mapp22;
8311       for(int j=0;j<nnode;j++)
8312         {
8313           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8314           int nnid=c[(*cI)+j+1];
8315           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8316           mapp22[nn]=nnid+offset1;
8317         }
8318       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8319       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8320         ((*it).second.first)->decrRef();
8321       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8322       std::map<INTERP_KERNEL::Node *,int> mapp3;
8323       for(std::size_t j=0;j<divs.size();j++)
8324         {
8325           int id=divs[j];
8326           INTERP_KERNEL::Node *tmp=0;
8327           if(id<offset1)
8328             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8329           else if(id<offset2)
8330             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8331           else
8332             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8333           addNodes[j]=tmp;
8334           mapp3[tmp]=id;
8335         }
8336       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8337       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8338         (*it)->decrRef();
8339       e->decrRef();
8340     }
8341 }
8342
8343 /*!
8344  * 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).
8345  * 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
8346  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8347  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8348  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8349  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8350  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8351  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8352  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8353  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8354  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8355  * \param [out] cut3DSuf input/output param.
8356  */
8357 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8358                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8359                                                    const int *desc, const int *descIndx, 
8360                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8361 {
8362   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8363   int nbOf3DSurfCell=(int)cut3DSurf.size();
8364   for(int i=0;i<nbOf3DSurfCell;i++)
8365     {
8366       std::vector<int> res;
8367       int offset=descIndx[i];
8368       int nbOfSeg=descIndx[i+1]-offset;
8369       for(int j=0;j<nbOfSeg;j++)
8370         {
8371           int edgeId=desc[offset+j];
8372           int status=cut3DCurve[edgeId];
8373           if(status!=-2)
8374             {
8375               if(status>-1)
8376                 res.push_back(status);
8377               else
8378                 {
8379                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8380                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8381                 }
8382             }
8383         }
8384       switch(res.size())
8385         {
8386         case 2:
8387           {
8388             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8389             break;
8390           }
8391         case 1:
8392         case 0:
8393           {
8394             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8395             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8396             if(res.size()==2)
8397               {
8398                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8399               }
8400             else
8401               {
8402                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8403               }
8404             break;
8405           }
8406         default:
8407           {// case when plane is on a multi colinear edge of a polyhedron
8408             if((int)res.size()==2*nbOfSeg)
8409               {
8410                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8411               }
8412             else
8413               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8414           }
8415         }
8416     }
8417 }
8418
8419 /*!
8420  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8421  * 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).
8422  * 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
8423  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8424  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8425  * \param desc is the descending connectivity 3D->3DSurf
8426  * \param descIndx is the descending connectivity index 3D->3DSurf
8427  */
8428 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8429                                                   const int *desc, const int *descIndx,
8430                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8431 {
8432   checkFullyDefined();
8433   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8434     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8435   const int *nodal3D=_nodal_connec->getConstPointer();
8436   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8437   int nbOfCells=getNumberOfCells();
8438   for(int i=0;i<nbOfCells;i++)
8439     {
8440       std::map<int, std::set<int> > m;
8441       int offset=descIndx[i];
8442       int nbOfFaces=descIndx[i+1]-offset;
8443       int start=-1;
8444       int end=-1;
8445       for(int j=0;j<nbOfFaces;j++)
8446         {
8447           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8448           if(p.first!=-1 && p.second!=-1)
8449             {
8450               if(p.first!=-2)
8451                 {
8452                   start=p.first; end=p.second;
8453                   m[p.first].insert(p.second);
8454                   m[p.second].insert(p.first);
8455                 }
8456               else
8457                 {
8458                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8459                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8460                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8461                   INTERP_KERNEL::NormalizedCellType cmsId;
8462                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8463                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8464                   for(unsigned k=0;k<nbOfNodesSon;k++)
8465                     {
8466                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8467                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8468                     }
8469                 }
8470             }
8471         }
8472       if(m.empty())
8473         continue;
8474       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8475       int prev=end;
8476       while(end!=start)
8477         {
8478           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8479           const std::set<int>& s=(*it).second;
8480           std::set<int> s2; s2.insert(prev);
8481           std::set<int> s3;
8482           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8483           if(s3.size()==1)
8484             {
8485               int val=*s3.begin();
8486               conn.push_back(start);
8487               prev=start;
8488               start=val;
8489             }
8490           else
8491             start=end;
8492         }
8493       conn.push_back(end);
8494       if(conn.size()>3)
8495         {
8496           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8497           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8498           cellIds->pushBackSilent(i);
8499         }
8500     }
8501 }
8502
8503 /*!
8504  * 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
8505  * 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
8506  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8507  * 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
8508  * 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.
8509  * 
8510  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8511  */
8512 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8513 {
8514   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8515   if(sz>=4)
8516     {
8517       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8518       if(cm.getDimension()==2)
8519         {
8520           const int *node=nodalConnBg+1;
8521           int startNode=*node++;
8522           double refX=coords[2*startNode];
8523           for(;node!=nodalConnEnd;node++)
8524             {
8525               if(coords[2*(*node)]<refX)
8526                 {
8527                   startNode=*node;
8528                   refX=coords[2*startNode];
8529                 }
8530             }
8531           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8532           refX=1e300;
8533           double tmp1;
8534           double tmp2[2];
8535           double angle0=-M_PI/2;
8536           //
8537           int nextNode=-1;
8538           int prevNode=-1;
8539           double resRef;
8540           double angleNext=0.;
8541           while(nextNode!=startNode)
8542             {
8543               nextNode=-1;
8544               resRef=1e300;
8545               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8546                 {
8547                   if(*node!=tmpOut.back() && *node!=prevNode)
8548                     {
8549                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8550                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8551                       double res;
8552                       if(angleM<=angle0)
8553                         res=angle0-angleM;
8554                       else
8555                         res=angle0-angleM+2.*M_PI;
8556                       if(res<resRef)
8557                         {
8558                           nextNode=*node;
8559                           resRef=res;
8560                           angleNext=angleM;
8561                         }
8562                     }
8563                 }
8564               if(nextNode!=startNode)
8565                 {
8566                   angle0=angleNext-M_PI;
8567                   if(angle0<-M_PI)
8568                     angle0+=2*M_PI;
8569                   prevNode=tmpOut.back();
8570                   tmpOut.push_back(nextNode);
8571                 }
8572             }
8573           std::vector<int> tmp3(2*(sz-1));
8574           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8575           std::copy(nodalConnBg+1,nodalConnEnd,it);
8576           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8577             {
8578               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8579               return false;
8580             }
8581           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8582             {
8583               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8584               return false;
8585             }
8586           else
8587             {
8588               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8589               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8590               return true;
8591             }
8592         }
8593       else
8594         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8595     }
8596   else
8597     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8598 }
8599
8600 /*!
8601  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8602  * 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.
8603  * 
8604  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8605  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8606  * \param [in,out] arr array in which the remove operation will be done.
8607  * \param [in,out] arrIndx array in the remove operation will modify
8608  * \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])
8609  * \return true if \b arr and \b arrIndx have been modified, false if not.
8610  */
8611 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8612 {
8613   if(!arrIndx || !arr)
8614     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8615   if(offsetForRemoval<0)
8616     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8617   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8618   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8619   int *arrIPtr=arrIndx->getPointer();
8620   *arrIPtr++=0;
8621   int previousArrI=0;
8622   const int *arrPtr=arr->getConstPointer();
8623   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8624   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8625     {
8626       if(*arrIPtr-previousArrI>offsetForRemoval)
8627         {
8628           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8629             {
8630               if(s.find(*work)==s.end())
8631                 arrOut.push_back(*work);
8632             }
8633         }
8634       previousArrI=*arrIPtr;
8635       *arrIPtr=(int)arrOut.size();
8636     }
8637   if(arr->getNumberOfTuples()==(int)arrOut.size())
8638     return false;
8639   arr->alloc((int)arrOut.size(),1);
8640   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8641   return true;
8642 }
8643
8644 /*!
8645  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8646  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8647  * The selection of extraction is done standardly in new2old format.
8648  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8649  *
8650  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8651  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8652  * \param [in] arrIn arr origin array from which the extraction will be done.
8653  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8654  * \param [out] arrOut the resulting array
8655  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8656  */
8657 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8658                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8659 {
8660   if(!arrIn || !arrIndxIn)
8661     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8662   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8663   const int *arrInPtr=arrIn->getConstPointer();
8664   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8665   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8666   int maxSizeOfArr=arrIn->getNumberOfTuples();
8667   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8668   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8669   arrIo->alloc((int)(sz+1),1);
8670   const int *idsIt=idsOfSelectBg;
8671   int *work=arrIo->getPointer();
8672   *work++=0;
8673   int lgth=0;
8674   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8675     {
8676       if(*idsIt>=0 && *idsIt<nbOfGrps)
8677         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8678       else
8679         {
8680           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8681           throw INTERP_KERNEL::Exception(oss.str().c_str());
8682         }
8683       if(lgth>=work[-1])
8684         *work=lgth;
8685       else
8686         {
8687           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8688           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8689           throw INTERP_KERNEL::Exception(oss.str().c_str());
8690         }
8691     }
8692   arro->alloc(lgth,1);
8693   work=arro->getPointer();
8694   idsIt=idsOfSelectBg;
8695   for(std::size_t i=0;i<sz;i++,idsIt++)
8696     {
8697       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8698         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8699       else
8700         {
8701           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8702           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8703           throw INTERP_KERNEL::Exception(oss.str().c_str());
8704         }
8705     }
8706   arrOut=arro.retn();
8707   arrIndexOut=arrIo.retn();
8708 }
8709
8710 /*!
8711  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8712  * 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
8713  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8714  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8715  *
8716  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8717  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8718  * \param [in] arrIn arr origin array from which the extraction will be done.
8719  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8720  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8721  * \param [in] srcArrIndex index array of \b srcArr
8722  * \param [out] arrOut the resulting array
8723  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8724  * 
8725  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8726  */
8727 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8728                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8729                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8730 {
8731   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8732     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8733   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8734   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8735   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8736   std::vector<bool> v(nbOfTuples,true);
8737   int offset=0;
8738   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8739   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8740   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8741     {
8742       if(*it>=0 && *it<nbOfTuples)
8743         {
8744           v[*it]=false;
8745           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8746         }
8747       else
8748         {
8749           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8750           throw INTERP_KERNEL::Exception(oss.str().c_str());
8751         }
8752     }
8753   srcArrIndexPtr=srcArrIndex->getConstPointer();
8754   arrIo->alloc(nbOfTuples+1,1);
8755   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8756   const int *arrInPtr=arrIn->getConstPointer();
8757   const int *srcArrPtr=srcArr->getConstPointer();
8758   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8759   int *arroPtr=arro->getPointer();
8760   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8761     {
8762       if(v[ii])
8763         {
8764           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8765           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8766         }
8767       else
8768         {
8769           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8770           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8771           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8772         }
8773     }
8774   arrOut=arro.retn();
8775   arrIndexOut=arrIo.retn();
8776 }
8777
8778 /*!
8779  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8780  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8781  *
8782  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8783  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8784  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8785  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8786  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8787  * \param [in] srcArrIndex index array of \b srcArr
8788  * 
8789  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8790  */
8791 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8792                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8793 {
8794   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8795     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8796   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8797   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8798   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8799   int *arrInOutPtr=arrInOut->getPointer();
8800   const int *srcArrPtr=srcArr->getConstPointer();
8801   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8802     {
8803       if(*it>=0 && *it<nbOfTuples)
8804         {
8805           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8806             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8807           else
8808             {
8809               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] !";
8810               throw INTERP_KERNEL::Exception(oss.str().c_str());
8811             }
8812         }
8813       else
8814         {
8815           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8816           throw INTERP_KERNEL::Exception(oss.str().c_str());
8817         }
8818     }
8819 }
8820
8821 /*!
8822  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8823  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8824  * 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]].
8825  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8826  * A negative value in \b arrIn means that it is ignored.
8827  * 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.
8828  * 
8829  * \param [in] arrIn arr origin array from which the extraction will be done.
8830  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8831  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8832  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8833  */
8834 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
8835 {
8836   int seed=0,nbOfDepthPeelingPerformed=0;
8837   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8838 }
8839
8840 /*!
8841  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8842  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8843  * 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]].
8844  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8845  * A negative value in \b arrIn means that it is ignored.
8846  * 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.
8847  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8848  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8849  * \param [in] arrIn arr origin array from which the extraction will be done.
8850  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8851  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8852  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8853  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8854  * \sa MEDCouplingUMesh::partitionBySpreadZone
8855  */
8856 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8857 {
8858   nbOfDepthPeelingPerformed=0;
8859   if(!arrIndxIn)
8860     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8861   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8862   if(nbOfTuples<=0)
8863     {
8864       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8865       return ret;
8866     }
8867   //
8868   std::vector<bool> fetched(nbOfTuples,false);
8869   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8870 }
8871
8872 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8873 {
8874   nbOfDepthPeelingPerformed=0;
8875   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
8876     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
8877   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8878   std::vector<bool> fetched2(nbOfTuples,false);
8879   int i=0;
8880   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
8881     {
8882       if(*seedElt>=0 && *seedElt<nbOfTuples)
8883         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
8884       else
8885         { 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()); }
8886     }
8887   const int *arrInPtr=arrIn->getConstPointer();
8888   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8889   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
8890   std::vector<int> idsToFetch1(seedBg,seedEnd);
8891   std::vector<int> idsToFetch2;
8892   std::vector<int> *idsToFetch=&idsToFetch1;
8893   std::vector<int> *idsToFetchOther=&idsToFetch2;
8894   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
8895     {
8896       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
8897         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
8898           if(!fetched[*it2])
8899             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
8900       std::swap(idsToFetch,idsToFetchOther);
8901       idsToFetchOther->clear();
8902       nbOfDepthPeelingPerformed++;
8903     }
8904   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
8905   i=0;
8906   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
8907   int *retPtr=ret->getPointer();
8908   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
8909     if(*it)
8910       *retPtr++=i;
8911   return ret.retn();
8912 }
8913
8914 /*!
8915  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8916  * 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
8917  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8918  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8919  *
8920  * \param [in] start begin of set of ids of the input extraction (included)
8921  * \param [in] end end of set of ids of the input extraction (excluded)
8922  * \param [in] step step of the set of ids in range mode.
8923  * \param [in] arrIn arr origin array from which the extraction will be done.
8924  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8925  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8926  * \param [in] srcArrIndex index array of \b srcArr
8927  * \param [out] arrOut the resulting array
8928  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8929  * 
8930  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8931  */
8932 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8933                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8934                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8935 {
8936   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8937     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
8938   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8939   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8940   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8941   int offset=0;
8942   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8943   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8944   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
8945   int it=start;
8946   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8947     {
8948       if(it>=0 && it<nbOfTuples)
8949         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
8950       else
8951         {
8952           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8953           throw INTERP_KERNEL::Exception(oss.str().c_str());
8954         }
8955     }
8956   srcArrIndexPtr=srcArrIndex->getConstPointer();
8957   arrIo->alloc(nbOfTuples+1,1);
8958   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8959   const int *arrInPtr=arrIn->getConstPointer();
8960   const int *srcArrPtr=srcArr->getConstPointer();
8961   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8962   int *arroPtr=arro->getPointer();
8963   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8964     {
8965       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
8966       if(pos<0)
8967         {
8968           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8969           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8970         }
8971       else
8972         {
8973           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8974           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8975         }
8976     }
8977   arrOut=arro.retn();
8978   arrIndexOut=arrIo.retn();
8979 }
8980
8981 /*!
8982  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8983  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8984  *
8985  * \param [in] start begin of set of ids of the input extraction (included)
8986  * \param [in] end end of set of ids of the input extraction (excluded)
8987  * \param [in] step step of the set of ids in range mode.
8988  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8989  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8990  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8991  * \param [in] srcArrIndex index array of \b srcArr
8992  * 
8993  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8994  */
8995 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8996                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8997 {
8998   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8999     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9000   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9001   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9002   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9003   int *arrInOutPtr=arrInOut->getPointer();
9004   const int *srcArrPtr=srcArr->getConstPointer();
9005   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9006   int it=start;
9007   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9008     {
9009       if(it>=0 && it<nbOfTuples)
9010         {
9011           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9012             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9013           else
9014             {
9015               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9016               throw INTERP_KERNEL::Exception(oss.str().c_str());
9017             }
9018         }
9019       else
9020         {
9021           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9022           throw INTERP_KERNEL::Exception(oss.str().c_str());
9023         }
9024     }
9025 }
9026
9027 /*!
9028  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9029  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9030  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9031  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9032  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9033  * 
9034  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9035  */
9036 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9037 {
9038   checkFullyDefined();
9039   int mdim=getMeshDimension();
9040   int spaceDim=getSpaceDimension();
9041   if(mdim!=spaceDim)
9042     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9043   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9044   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9045   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9046   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9047   ret->setCoords(getCoords());
9048   ret->allocateCells((int)partition.size());
9049   //
9050   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9051     {
9052       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9053       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9054       switch(mdim)
9055         {
9056         case 2:
9057           cell=tmp->buildUnionOf2DMesh();
9058           break;
9059         case 3:
9060           cell=tmp->buildUnionOf3DMesh();
9061           break;
9062         default:
9063           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9064         }
9065       
9066       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9067     }
9068   //
9069   ret->finishInsertingCells();
9070   return ret.retn();
9071 }
9072
9073 /*!
9074  * This method partitions \b this into contiguous zone.
9075  * This method only needs a well defined connectivity. Coordinates are not considered here.
9076  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9077  */
9078 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9079 {
9080   //#if 0
9081   int nbOfCellsCur=getNumberOfCells();
9082   std::vector<DataArrayInt *> ret;
9083   if(nbOfCellsCur<=0)
9084     return ret;
9085   DataArrayInt *neigh=0,*neighI=0;
9086   computeNeighborsOfCells(neigh,neighI);
9087   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9088   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9089   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9090   int seed=0;
9091   while(seed<nbOfCellsCur)
9092     {
9093       int nbOfPeelPerformed=0;
9094       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9095       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9096     }
9097   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9098     ret.push_back((*it).retn());
9099   return ret;
9100   //#endif
9101 #if 0
9102   int nbOfCellsCur=getNumberOfCells();
9103   DataArrayInt *neigh=0,*neighI=0;
9104   computeNeighborsOfCells(neigh,neighI);
9105   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9106   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9107   std::vector<DataArrayInt *> ret;
9108   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9109   while(nbOfCellsCur>0)
9110     {
9111       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9112       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9113       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9114       ret2.push_back(tmp2);  ret.push_back(tmp2);
9115       nbOfCellsCur=tmp3->getNumberOfTuples();
9116       if(nbOfCellsCur>0)
9117         {
9118           ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9119           MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9120           neighAuto=neigh;
9121           neighIAuto=neighI;
9122           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9123           neighAuto->transformWithIndArr(renum->begin(),renum->end());
9124         }
9125     }
9126   for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9127     (*it)->incrRef();
9128   return ret;
9129 #endif
9130 }
9131
9132 /*!
9133  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9134  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9135  *
9136  * \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.
9137  * \return a newly allocated DataArrayInt to be managed by the caller.
9138  * \throw In case of \a code has not the right format (typically of size 3*n)
9139  */
9140 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9141 {
9142   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9143   std::size_t nb=code.size()/3;
9144   if(code.size()%3!=0)
9145     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9146   ret->alloc((int)nb,2);
9147   int *retPtr=ret->getPointer();
9148   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9149     {
9150       retPtr[0]=code[3*i+2];
9151       retPtr[1]=code[3*i+2]+code[3*i+1];
9152     }
9153   return ret.retn();
9154 }
9155
9156 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9157                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9158 {
9159   if(mesh)
9160     {
9161       mesh->incrRef();
9162       _nb_cell=mesh->getNumberOfCells();
9163     }
9164 }
9165
9166 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9167 {
9168   if(_mesh)
9169     _mesh->decrRef();
9170   if(_own_cell)
9171     delete _cell;
9172 }
9173
9174 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9175                                                                                                                                _own_cell(false),_cell_id(bg-1),
9176                                                                                                                                _nb_cell(end)
9177 {
9178   if(mesh)
9179     mesh->incrRef();
9180 }
9181
9182 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9183 {
9184   _cell_id++;
9185   if(_cell_id<_nb_cell)
9186     {
9187       _cell->next();
9188       return _cell;
9189     }
9190   else
9191     return 0;
9192 }
9193
9194 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9195 {
9196   if(_mesh)
9197     _mesh->incrRef();
9198 }
9199
9200 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9201 {
9202   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9203 }
9204
9205 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9206 {
9207   if(_mesh)
9208     _mesh->decrRef();
9209 }
9210
9211 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9212                                                                                                                                                                   _itc(itc),
9213                                                                                                                                                                   _bg(bg),_end(end)
9214 {
9215   if(_mesh)
9216     _mesh->incrRef();
9217 }
9218
9219 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9220 {
9221   if(_mesh)
9222     _mesh->decrRef();
9223 }
9224
9225 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9226 {
9227   return _type;
9228 }
9229
9230 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9231 {
9232   return _end-_bg;
9233 }
9234
9235 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9236 {
9237   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9238 }
9239
9240 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9241 {
9242   if(mesh)
9243     {
9244       mesh->incrRef();
9245       _nb_cell=mesh->getNumberOfCells();
9246     }
9247 }
9248
9249 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9250 {
9251   if(_mesh)
9252     _mesh->decrRef();
9253   delete _cell;
9254 }
9255
9256 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9257 {
9258   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9259   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9260   if(_cell_id<_nb_cell)
9261     {
9262       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9263       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9264       int startId=_cell_id;
9265       _cell_id+=nbOfElems;
9266       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9267     }
9268   else
9269     return 0;
9270 }
9271
9272 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9273 {
9274   if(mesh)
9275     {
9276       _conn=mesh->getNodalConnectivity()->getPointer();
9277       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9278     }
9279 }
9280
9281 void MEDCouplingUMeshCell::next()
9282 {
9283   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9284     {
9285       _conn+=_conn_lgth;
9286       _conn_indx++;
9287     }
9288   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9289 }
9290
9291 std::string MEDCouplingUMeshCell::repr() const
9292 {
9293   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9294     {
9295       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9296       oss << " : ";
9297       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9298       return oss.str();
9299     }
9300   else
9301     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9302 }
9303
9304 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9305 {
9306   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9307     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9308   else
9309     return INTERP_KERNEL::NORM_ERROR;
9310 }
9311
9312 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9313 {
9314   lgth=_conn_lgth;
9315   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9316     return _conn;
9317   else
9318     return 0;
9319 }