Salome HOME
On the road of addition of optimized unstructured mesh with a single geometric type.
[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   int newNbOfNodes=-1;
1438   DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1439   renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1440   return traducer;
1441 }
1442
1443 /*!
1444  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1445  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1446  */
1447 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1448 {
1449   switch(compType)
1450     {
1451     case 0:
1452       return AreCellsEqual0(conn,connI,cell1,cell2);
1453     case 1:
1454       return AreCellsEqual1(conn,connI,cell1,cell2);
1455     case 2:
1456       return AreCellsEqual2(conn,connI,cell1,cell2);
1457     case 3:
1458       return AreCellsEqual3(conn,connI,cell1,cell2);
1459     case 7:
1460       return AreCellsEqual7(conn,connI,cell1,cell2);
1461     }
1462   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1463 }
1464
1465 /*!
1466  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1467  */
1468 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1469 {
1470   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1471     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1472   return 0;
1473 }
1474
1475 /*!
1476  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1477  */
1478 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1479 {
1480   int sz=connI[cell1+1]-connI[cell1];
1481   if(sz==connI[cell2+1]-connI[cell2])
1482     {
1483       if(conn[connI[cell1]]==conn[connI[cell2]])
1484         {
1485           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1486           unsigned dim=cm.getDimension();
1487           if(dim!=3)
1488             {
1489               if(dim!=1)
1490                 {
1491                   int sz1=2*(sz-1);
1492                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1493                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1494                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1495                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1496                   return work!=tmp+sz1?1:0;
1497                 }
1498               else
1499                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1500             }
1501           else
1502             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1503         }
1504     }
1505   return 0;
1506 }
1507
1508 /*!
1509  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1510  */
1511 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1512 {
1513   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1514     {
1515       if(conn[connI[cell1]]==conn[connI[cell2]])
1516         {
1517           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1518           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1519           return s1==s2?1:0;
1520         }
1521     }
1522   return 0;
1523 }
1524
1525 /*!
1526  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1527  */
1528 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1529 {
1530   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1531     {
1532       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1533       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1534       return s1==s2?1:0;
1535     }
1536   return 0;
1537 }
1538
1539 /*!
1540  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1541  */
1542 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1543 {
1544   int sz=connI[cell1+1]-connI[cell1];
1545   if(sz==connI[cell2+1]-connI[cell2])
1546     {
1547       if(conn[connI[cell1]]==conn[connI[cell2]])
1548         {
1549           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1550           unsigned dim=cm.getDimension();
1551           if(dim!=3)
1552             {
1553               if(dim!=1)
1554                 {
1555                   int sz1=2*(sz-1);
1556                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1557                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1558                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1559                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1560                   if(work!=tmp+sz1)
1561                     return 1;
1562                   else
1563                     {
1564                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1565                       std::reverse_iterator<int *> it2((int *)tmp);
1566                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1567                         return 2;
1568                       else
1569                         return 0;
1570                     }
1571                   
1572                   return work!=tmp+sz1?1:0;
1573                 }
1574               else
1575                 {//case of SEG2 and SEG3
1576                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1577                     return 1;
1578                   if(!cm.isQuadratic())
1579                     {
1580                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1581                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1582                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1583                         return 2;
1584                       return 0;
1585                     }
1586                   else
1587                     {
1588                       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])
1589                         return 2;
1590                       return 0;
1591                     }
1592                 }
1593             }
1594           else
1595             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1596         }
1597     }
1598   return 0;
1599 }
1600
1601 /*!
1602  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1603  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1604  * and result remains unchanged.
1605  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1606  * If in 'candidates' pool -1 value is considered as an empty value.
1607  * WARNING this method returns only ONE set of result !
1608  */
1609 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1610 {
1611   if(candidates.size()<1)
1612     return false;
1613   bool ret=false;
1614   std::vector<int>::const_iterator iter=candidates.begin();
1615   int start=(*iter++);
1616   for(;iter!=candidates.end();iter++)
1617     {
1618       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1619       if(status!=0)
1620         {
1621           if(!ret)
1622             {
1623               result->pushBackSilent(start);
1624               ret=true;
1625             }
1626           if(status==1)
1627             result->pushBackSilent(*iter);
1628           else
1629             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1630         }
1631     }
1632   return ret;
1633 }
1634
1635 /*!
1636  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1637  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1638  *
1639  * \param [in] compType input specifying the technique used to compare cells each other.
1640  *   - 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.
1641  *   - 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)
1642  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1643  *   - 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
1644  * can be used for users not sensitive to orientation of cell
1645  * \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.
1646  * \param [out] commonCells
1647  * \param [out] commonCellsI
1648  * \return the correspondance array old to new in a newly allocated array.
1649  * 
1650  */
1651 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1652 {
1653   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1654   getReverseNodalConnectivity(revNodal,revNodalI);
1655   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1656 }
1657
1658 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1659                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1660 {
1661   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1662   int nbOfCells=nodalI->getNumberOfTuples()-1;
1663   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1664   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1665   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1666   std::vector<bool> isFetched(nbOfCells,false);
1667   if(startCellId==0)
1668     {
1669       for(int i=0;i<nbOfCells;i++)
1670         {
1671           if(!isFetched[i])
1672             {
1673               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1674               std::vector<int> v,v2;
1675               if(connOfNode!=connPtr+connIPtr[i+1])
1676                 {
1677                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1678                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1679                   connOfNode++;
1680                 }
1681               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1682                 if(*connOfNode>=0)
1683                   {
1684                     v=v2;
1685                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1686                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1687                     v2.resize(std::distance(v2.begin(),it));
1688                   }
1689               if(v2.size()>1)
1690                 {
1691                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1692                     {
1693                       int pos=commonCellsI->back();
1694                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1695                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1696                         isFetched[*it]=true;
1697                     }
1698                 }
1699             }
1700         }
1701     }
1702   else
1703     {
1704       for(int i=startCellId;i<nbOfCells;i++)
1705         {
1706           if(!isFetched[i])
1707             {
1708               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1709               std::vector<int> v,v2;
1710               if(connOfNode!=connPtr+connIPtr[i+1])
1711                 {
1712                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1713                   connOfNode++;
1714                 }
1715               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1716                 if(*connOfNode>=0)
1717                   {
1718                     v=v2;
1719                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1720                     v2.resize(std::distance(v2.begin(),it));
1721                   }
1722               if(v2.size()>1)
1723                 {
1724                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1725                     {
1726                       int pos=commonCellsI->back();
1727                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1728                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1729                         isFetched[*it]=true;
1730                     }
1731                 }
1732             }
1733         }
1734     }
1735   commonCellsArr=commonCells.retn();
1736   commonCellsIArr=commonCellsI.retn();
1737 }
1738
1739 /*!
1740  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1741  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1742  * than \a other->getNumberOfCells() in the returned array means that there is no
1743  * corresponding cell in \a this mesh.
1744  * It is expected that \a this and \a other meshes share the same node coordinates
1745  * array, if it is not so an exception is thrown. 
1746  *  \param [in] other - the mesh to compare with.
1747  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1748  *         valid values [0,1,2], see zipConnectivityTraducer().
1749  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1750  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1751  *         values. The caller is to delete this array using
1752  *         decrRef() as it is no more needed.
1753  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1754  *         mesh.
1755  *
1756  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1757  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1758  *  \sa checkDeepEquivalOnSameNodesWith()
1759  *  \sa checkGeoEquivalWith()
1760  */
1761 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1762 {
1763   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1764   int nbOfCells=getNumberOfCells();
1765   static const int possibleCompType[]={0,1,2};
1766   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1767     {
1768       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1769       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1770       oss << " !";
1771       throw INTERP_KERNEL::Exception(oss.str().c_str());
1772     }
1773   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1774   arr=o2n->substr(nbOfCells);
1775   arr->setName(other->getName());
1776   int tmp;
1777   if(other->getNumberOfCells()==0)
1778     return true;
1779   return arr->getMaxValue(tmp)<nbOfCells;
1780 }
1781
1782 /*!
1783  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1784  * This method tries to determine if \b other is fully included in \b this.
1785  * The main difference is that this method is not expected to throw exception.
1786  * This method has two outputs :
1787  *
1788  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1789  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1790  */
1791 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1792 {
1793   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1794   DataArrayInt *commonCells=0,*commonCellsI=0;
1795   int thisNbCells=getNumberOfCells();
1796   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1797   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1798   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1799   int otherNbCells=other->getNumberOfCells();
1800   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1801   arr2->alloc(otherNbCells,1);
1802   arr2->fillWithZero();
1803   int *arr2Ptr=arr2->getPointer();
1804   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1805   for(int i=0;i<nbOfCommon;i++)
1806     {
1807       int start=commonCellsPtr[commonCellsIPtr[i]];
1808       if(start<thisNbCells)
1809         {
1810           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1811             {
1812               int sig=commonCellsPtr[j]>0?1:-1;
1813               int val=std::abs(commonCellsPtr[j])-1;
1814               if(val>=thisNbCells)
1815                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1816             }
1817         }
1818     }
1819   arr2->setName(other->getName());
1820   if(arr2->presenceOfValue(0))
1821     return false;
1822   arr=arr2.retn();
1823   return true;
1824 }
1825
1826 /*!
1827  * Merges nodes equal within \a precision and returns an array describing the 
1828  * permutation used to remove duplicate nodes.
1829  *  \param [in] precision - minimal absolute distance between two nodes at which they are
1830  *              considered not coincident.
1831  *  \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1832  *  \param [out] newNbOfNodes - number of nodes remaining after the removal.
1833  *  \return DataArrayInt * - the permutation array in "Old to New" mode. For more 
1834  *          info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1835  *          is to delete this array using decrRef() as it is no more needed.
1836  *  \throw If the coordinates array is not set.
1837  *  \throw If the nodal connectivity of cells is not defined.
1838  *
1839  *  \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1840  *  \ref  py_mcumesh_mergeNodes "Here is a Python example".
1841  */
1842 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1843 {
1844   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1845   if(areNodesMerged)
1846     renumberNodes(ret->begin(),newNbOfNodes);
1847   return ret.retn();
1848 }
1849
1850
1851 /*!
1852  * Merges nodes equal within \a precision and returns an array describing the 
1853  * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
1854  *  of merged nodes is changed to be at their barycenter.
1855  *  \param [in] precision - minimal absolute distance between two nodes at which they are
1856  *              considered not coincident.
1857  *  \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1858  *  \param [out] newNbOfNodes - number of nodes remaining after the removal.
1859  *  \return DataArrayInt * - the permutation array in "Old to New" mode. For more 
1860  *          info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1861  *          is to delete this array using decrRef() as it is no more needed.
1862  *  \throw If the coordinates array is not set.
1863  *  \throw If the nodal connectivity of cells is not defined.
1864  *
1865  *  \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1866  *  \ref  py_mcumesh_mergeNodes "Here is a Python example".
1867  */
1868 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
1869 {
1870   DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1871   if(areNodesMerged)
1872     renumberNodes2(ret->getConstPointer(),newNbOfNodes);
1873   return ret;
1874 }
1875
1876 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1877 {
1878   if(!other)
1879     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1880   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1881   if(!otherC)
1882     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1883   std::vector<const MEDCouplingUMesh *> ms(2);
1884   ms[0]=this;
1885   ms[1]=otherC;
1886   return MergeUMeshesOnSameCoords(ms);
1887 }
1888
1889 /*!
1890  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1891  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1892  * cellIds is not given explicitely but by a range python like.
1893  * 
1894  * \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.
1895  * \return a newly allocated
1896  * 
1897  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1898  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1899  */
1900 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1901 {
1902   if(getMeshDimension()!=-1)
1903     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1904   else
1905     {
1906       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1907       if(newNbOfCells!=1)
1908         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1909       if(start!=0)
1910         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1911       incrRef();
1912       return const_cast<MEDCouplingUMesh *>(this);
1913     }
1914 }
1915
1916 /*!
1917  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1918  * The result mesh shares or not the node coordinates array with \a this mesh depending
1919  * on \a keepCoords parameter.
1920  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1921  *           to write this mesh to the MED file, its cells must be sorted using
1922  *           sortCellsInMEDFileFrmt().
1923  *  \param [in] begin - an array of cell ids to include to the new mesh.
1924  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1925  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1926  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1927  *         by calling zipCoords().
1928  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1929  *         to delete this mesh using decrRef() as it is no more needed. 
1930  *  \throw If the coordinates array is not set.
1931  *  \throw If the nodal connectivity of cells is not defined.
1932  *  \throw If any cell id in the array \a begin is not valid.
1933  *
1934  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1935  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1936  */
1937 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1938 {
1939   if(getMeshDimension()!=-1)
1940     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1941   else
1942     {
1943       if(end-begin!=1)
1944         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1945       if(begin[0]!=0)
1946         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1947       incrRef();
1948       return const_cast<MEDCouplingUMesh *>(this);
1949     }
1950 }
1951
1952 /*!
1953  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1954  *
1955  * 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.
1956  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1957  * The number of cells of \b this will remain the same with this method.
1958  *
1959  * \param [in] begin begin of cell ids (included) of cells in this to assign
1960  * \param [in] end end of cell ids (excluded) of cells in this to assign
1961  * \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 ).
1962  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1963  */
1964 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1965 {
1966   checkConnectivityFullyDefined();
1967   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1968   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1969     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1970   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1971     {
1972       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1973       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1974       throw INTERP_KERNEL::Exception(oss.str().c_str());
1975     }
1976   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1977   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1978     {
1979       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1980       throw INTERP_KERNEL::Exception(oss.str().c_str());
1981     }
1982   int nbOfCells=getNumberOfCells();
1983   bool easyAssign=true;
1984   const int *connI=_nodal_connec_index->getConstPointer();
1985   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1986   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1987     {
1988       if(*it>=0 && *it<nbOfCells)
1989         {
1990           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1991         }
1992       else
1993         {
1994           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1995           throw INTERP_KERNEL::Exception(oss.str().c_str());
1996         }
1997     }
1998   if(easyAssign)
1999     {
2000       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2001       computeTypes();
2002     }
2003   else
2004     {
2005       DataArrayInt *arrOut=0,*arrIOut=0;
2006       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2007                                                arrOut,arrIOut);
2008       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2009       setConnectivity(arrOut,arrIOut,true);
2010     }
2011 }
2012
2013 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2014 {
2015   checkConnectivityFullyDefined();
2016   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2017   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2018     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2019   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2020     {
2021       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2022       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2023       throw INTERP_KERNEL::Exception(oss.str().c_str());
2024     }
2025   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2026   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2027     {
2028       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2029       throw INTERP_KERNEL::Exception(oss.str().c_str());
2030     }
2031   int nbOfCells=getNumberOfCells();
2032   bool easyAssign=true;
2033   const int *connI=_nodal_connec_index->getConstPointer();
2034   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2035   int it=start;
2036   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2037     {
2038       if(it>=0 && it<nbOfCells)
2039         {
2040           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2041         }
2042       else
2043         {
2044           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2045           throw INTERP_KERNEL::Exception(oss.str().c_str());
2046         }
2047     }
2048   if(easyAssign)
2049     {
2050       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2051       computeTypes();
2052     }
2053   else
2054     {
2055       DataArrayInt *arrOut=0,*arrIOut=0;
2056       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2057                                                 arrOut,arrIOut);
2058       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2059       setConnectivity(arrOut,arrIOut,true);
2060     }
2061 }                      
2062
2063 /*!
2064  * Finds cells whose all nodes are in a given array of node ids.
2065  *  \param [in] partBg - the array of node ids.
2066  *  \param [in] partEnd - a pointer to a (last+1)-th element of \a partBg.
2067  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2068  *          cells. The caller is to delete this array using decrRef() as it is no
2069  *          more needed.
2070  *  \throw If the coordinates array is not set.
2071  *  \throw If the nodal connectivity of cells is not defined.
2072  *  \throw If any cell id in \a partBg is not valid.
2073  *
2074  *  \ref cpp_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a C++ example".<br>
2075  *  \ref  py_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a Python example".
2076  */
2077 DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
2078 {
2079   DataArrayInt *cellIdsKept=0;
2080   fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept);
2081   cellIdsKept->setName(getName());
2082   return cellIdsKept;
2083 }
2084
2085 /*!
2086  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2087  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2088  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2089  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2090  *
2091  * \param [in] begin input start of array of node ids.
2092  * \param [in] end input end of array of node ids.
2093  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2094  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2095  */
2096 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2097 {
2098   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2099   checkConnectivityFullyDefined();
2100   int tmp=-1;
2101   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2102   std::vector<bool> fastFinder(sz,false);
2103   for(const int *work=begin;work!=end;work++)
2104     if(*work>=0 && *work<sz)
2105       fastFinder[*work]=true;
2106   int nbOfCells=getNumberOfCells();
2107   const int *conn=getNodalConnectivity()->getConstPointer();
2108   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2109   for(int i=0;i<nbOfCells;i++)
2110     {
2111       int ref=0,nbOfHit=0;
2112       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2113         if(*work2>=0)
2114           {
2115             ref++;
2116             if(fastFinder[*work2])
2117               nbOfHit++;
2118           }
2119       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2120         cellIdsKept->pushBackSilent(i);
2121     }
2122   cellIdsKeptArr=cellIdsKept.retn();
2123 }
2124
2125 /*!
2126  * Finds cells whose all or some nodes are in a given array of node ids.
2127  *  \param [in] begin - the array of node ids.
2128  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2129  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2130  *         array \a begin are returned only, else cells whose any node is in the
2131  *         array \a begin are returned.
2132  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2133  *         cells. The caller is to delete this array using decrRef() as it is no more
2134  *         needed. 
2135  *  \throw If the coordinates array is not set.
2136  *  \throw If the nodal connectivity of cells is not defined.
2137  *  \throw If any cell id in \a begin is not valid.
2138  *
2139  *  \ref cpp_mcumesh_getCellIdsLyingOnNodes "Here is a C++ example".<br>
2140  *  \ref  py_mcumesh_getCellIdsLyingOnNodes "Here is a Python example".
2141  */
2142 DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
2143 {
2144   DataArrayInt *cellIdsKept=0;
2145   fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2146   cellIdsKept->setName(getName());
2147   return cellIdsKept;
2148 }
2149
2150 /*!
2151  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2152  * this->getMeshDimension(), that bound some cells of \a this mesh.
2153  * The cells of lower dimension to include to the result mesh are selected basing on
2154  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2155  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2156  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2157  * created mesh shares the node coordinates array with \a this mesh. 
2158  *  \param [in] begin - the array of node ids.
2159  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2160  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2161  *         array \a begin are added, else cells whose any node is in the
2162  *         array \a begin are added.
2163  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2164  *         to delete this mesh using decrRef() as it is no more needed. 
2165  *  \throw If the coordinates array is not set.
2166  *  \throw If the nodal connectivity of cells is not defined.
2167  *  \throw If any node id in \a begin is not valid.
2168  *
2169  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2170  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2171  */
2172 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2173 {
2174   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2175   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2176   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2177   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2178   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2179 }
2180
2181 /*!
2182  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2183  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2184  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2185  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2186  *         by calling zipCoords().
2187  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2188  *         to delete this mesh using decrRef() as it is no more needed. 
2189  *  \throw If the coordinates array is not set.
2190  *  \throw If the nodal connectivity of cells is not defined.
2191  *
2192  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2193  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2194  */
2195 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2196 {
2197   DataArrayInt *desc=DataArrayInt::New();
2198   DataArrayInt *descIndx=DataArrayInt::New();
2199   DataArrayInt *revDesc=DataArrayInt::New();
2200   DataArrayInt *revDescIndx=DataArrayInt::New();
2201   //
2202   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2203   revDesc->decrRef();
2204   desc->decrRef();
2205   descIndx->decrRef();
2206   int nbOfCells=meshDM1->getNumberOfCells();
2207   const int *revDescIndxC=revDescIndx->getConstPointer();
2208   std::vector<int> boundaryCells;
2209   for(int i=0;i<nbOfCells;i++)
2210     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2211       boundaryCells.push_back(i);
2212   revDescIndx->decrRef();
2213   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2214   return ret;
2215 }
2216
2217 /*!
2218  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2219  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2220  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2221  */
2222 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2223 {
2224   checkFullyDefined();
2225   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2226   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2227   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2228   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2229   //
2230   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2231   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2232   //
2233   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2234   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2235   const int *revDescPtr=revDesc->getConstPointer();
2236   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2237   int nbOfCells=getNumberOfCells();
2238   std::vector<bool> ret1(nbOfCells,false);
2239   int sz=0;
2240   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2241     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2242       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2243   //
2244   DataArrayInt *ret2=DataArrayInt::New();
2245   ret2->alloc(sz,1);
2246   int *ret2Ptr=ret2->getPointer();
2247   sz=0;
2248   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2249     if(*it)
2250       *ret2Ptr++=sz;
2251   ret2->setName("BoundaryCells");
2252   return ret2;
2253 }
2254
2255 /*!
2256  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2257  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2258  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2259  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2260  *
2261  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2262  * This method method returns cells ids set s = s1 + s2 where :
2263  * 
2264  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2265  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2266  *
2267  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2268  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2269  *
2270  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2271  * \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
2272  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2273  */
2274 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2275 {
2276   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2277     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2278   checkConnectivityFullyDefined();
2279   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2280   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2281     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2282   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2283   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2284   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2285   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2286   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2287   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2288   DataArrayInt *idsOtherInConsti=0;
2289   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2290   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2291   if(!b)
2292     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2293   std::set<int> s1;
2294   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2295     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2296   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2297   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2298   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2299   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2300   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2301   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2302   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2303   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2304   neighThisPartAuto=0;
2305   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2306   const int li[2]={0,1};
2307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2308   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2309   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2310   s_renum1->sort();
2311   //
2312   cellIdsRk0=s0arr.retn();
2313   cellIdsRk1=s_renum1.retn();
2314 }
2315
2316 /*!
2317  * 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
2318  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2319  * 
2320  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2321  */
2322 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2323 {
2324   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2325   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2326   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2327   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2328   //
2329   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2330   revDesc=0; desc=0; descIndx=0;
2331   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2332   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2333   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2334 }
2335
2336 /*!
2337  * Finds nodes lying on the boundary of \a this mesh.
2338  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2339  *          nodes. The caller is to delete this array using decrRef() as it is no
2340  *          more needed.
2341  *  \throw If the coordinates array is not set.
2342  *  \throw If the nodal connectivity of cells is node defined.
2343  *
2344  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2345  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2346  */
2347 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2348 {
2349   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2350   return skin->computeFetchedNodeIds();
2351 }
2352
2353 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2354 {
2355   incrRef();
2356   return const_cast<MEDCouplingUMesh *>(this);
2357 }
2358
2359 /*!
2360  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2361  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2362  * 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.
2363  * 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.
2364  * 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.
2365  *
2366  * \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
2367  *             parameter is altered during the call.
2368  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2369  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2370  * \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.
2371  *
2372  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2373  */
2374 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2375                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2376 {
2377   checkFullyDefined();
2378   otherDimM1OnSameCoords.checkFullyDefined();
2379   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2380     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2381   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2382     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2383   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2384   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2385   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2386   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2387   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2388   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2389   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2392   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2393   //
2394   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2395   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2396   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2397   DataArrayInt *idsTmp=0;
2398   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2400   if(!b)
2401     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2402   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2403   DataArrayInt *tmp0=0,*tmp1=0;
2404   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2405   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2406   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2407   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2408   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2409   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2410   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2411   //
2412   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2413   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2414   nodeIdsToDuplicate=s3.retn();
2415 }
2416
2417 /*!
2418  * This method operates a modification of the connectivity and coords in \b this.
2419  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2420  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2421  * 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
2422  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2423  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2424  * 
2425  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2426  * 
2427  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2428  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2429  */
2430 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2431 {
2432   int nbOfNodes=getNumberOfNodes();
2433   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2434   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2435 }
2436
2437 /*!
2438  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2439  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2440  * This method is a generalization of shiftNodeNumbersInConn().
2441  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2442  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2443  *         this->getNumberOfNodes(), in "Old to New" mode. 
2444  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2445  *  \throw If the nodal connectivity of cells is not defined.
2446  *
2447  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2448  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2449  */
2450 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2451 {
2452   checkConnectivityFullyDefined();
2453   int *conn=getNodalConnectivity()->getPointer();
2454   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2455   int nbOfCells=getNumberOfCells();
2456   for(int i=0;i<nbOfCells;i++)
2457     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2458       {
2459         int& node=conn[iconn];
2460         if(node>=0)//avoid polyhedron separator
2461           {
2462             node=newNodeNumbersO2N[node];
2463           }
2464       }
2465   _nodal_connec->declareAsNew();
2466   updateTime();
2467 }
2468
2469 /*!
2470  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2471  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2472  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2473  * 
2474  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2475  */
2476 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2477 {
2478   checkConnectivityFullyDefined();
2479   int *conn=getNodalConnectivity()->getPointer();
2480   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2481   int nbOfCells=getNumberOfCells();
2482   for(int i=0;i<nbOfCells;i++)
2483     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2484       {
2485         int& node=conn[iconn];
2486         if(node>=0)//avoid polyhedron separator
2487           {
2488             node+=delta;
2489           }
2490       }
2491   _nodal_connec->declareAsNew();
2492   updateTime();
2493 }
2494
2495 /*!
2496  * This method operates a modification of the connectivity in \b this.
2497  * 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.
2498  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2499  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2500  * 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
2501  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2502  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2503  * 
2504  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2505  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2506  * 
2507  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2508  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2509  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2510  */
2511 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2512 {
2513   checkConnectivityFullyDefined();
2514   std::map<int,int> m;
2515   int val=offset;
2516   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2517     m[*work]=val;
2518   int *conn=getNodalConnectivity()->getPointer();
2519   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2520   int nbOfCells=getNumberOfCells();
2521   for(int i=0;i<nbOfCells;i++)
2522     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2523       {
2524         int& node=conn[iconn];
2525         if(node>=0)//avoid polyhedron separator
2526           {
2527             std::map<int,int>::iterator it=m.find(node);
2528             if(it!=m.end())
2529               node=(*it).second;
2530           }
2531       }
2532   updateTime();
2533 }
2534
2535 /*!
2536  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2537  *
2538  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2539  * After the call of this method the number of cells remains the same as before.
2540  *
2541  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2542  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2543  * be strictly in [0;this->getNumberOfCells()).
2544  *
2545  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2546  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2547  * should be contained in[0;this->getNumberOfCells()).
2548  * 
2549  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2550  */
2551 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2552 {
2553   checkConnectivityFullyDefined();
2554   int nbCells=getNumberOfCells();
2555   const int *array=old2NewBg;
2556   if(check)
2557     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2558   //
2559   const int *conn=_nodal_connec->getConstPointer();
2560   const int *connI=_nodal_connec_index->getConstPointer();
2561   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2562   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2563   const int *n2oPtr=n2o->begin();
2564   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2565   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2566   newConn->copyStringInfoFrom(*_nodal_connec);
2567   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2568   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2569   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2570   //
2571   int *newC=newConn->getPointer();
2572   int *newCI=newConnI->getPointer();
2573   int loc=0;
2574   newCI[0]=loc;
2575   for(int i=0;i<nbCells;i++)
2576     {
2577       int pos=n2oPtr[i];
2578       int nbOfElts=connI[pos+1]-connI[pos];
2579       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2580       loc+=nbOfElts;
2581       newCI[i+1]=loc;
2582     }
2583   //
2584   setConnectivity(newConn,newConnI);
2585   if(check)
2586     free(const_cast<int *>(array));
2587 }
2588
2589 /*!
2590  * Finds cells whose bounding boxes intersect a given bounding box.
2591  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2592  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2593  *         zMax (if in 3D). 
2594  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2595  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2596  *         extent of the bounding box of cell to produce an addition to this bounding box.
2597  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2598  *         cells. The caller is to delete this array using decrRef() as it is no more
2599  *         needed. 
2600  *  \throw If the coordinates array is not set.
2601  *  \throw If the nodal connectivity of cells is not defined.
2602  *
2603  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2604  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2605  */
2606 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2607 {
2608   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2609   if(getMeshDimension()==-1)
2610     {
2611       elems->pushBackSilent(0);
2612       return elems.retn();
2613     }
2614   int dim=getSpaceDimension();
2615   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2616   const int* conn      = getNodalConnectivity()->getConstPointer();
2617   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2618   const double* coords = getCoords()->getConstPointer();
2619   int nbOfCells=getNumberOfCells();
2620   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2621     {
2622       for (int i=0; i<dim; i++)
2623         {
2624           elem_bb[i*2]=std::numeric_limits<double>::max();
2625           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2626         }
2627
2628       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2629         {
2630           int node= conn[inode];
2631           if(node>=0)//avoid polyhedron separator
2632             {
2633               for (int idim=0; idim<dim; idim++)
2634                 {
2635                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2636                     {
2637                       elem_bb[idim*2] = coords[node*dim+idim] ;
2638                     }
2639                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2640                     {
2641                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2642                     }
2643                 }
2644             }
2645         }
2646       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2647         elems->pushBackSilent(ielem);
2648     }
2649   return elems.retn();
2650 }
2651
2652 /*!
2653  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2654  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2655  * added in 'elems' parameter.
2656  */
2657 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2658 {
2659   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2660   if(getMeshDimension()==-1)
2661     {
2662       elems->pushBackSilent(0);
2663       return elems.retn();
2664     }
2665   int dim=getSpaceDimension();
2666   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2667   const int* conn      = getNodalConnectivity()->getConstPointer();
2668   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2669   const double* coords = getCoords()->getConstPointer();
2670   int nbOfCells=getNumberOfCells();
2671   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2672     {
2673       for (int i=0; i<dim; i++)
2674         {
2675           elem_bb[i*2]=std::numeric_limits<double>::max();
2676           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2677         }
2678
2679       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2680         {
2681           int node= conn[inode];
2682           if(node>=0)//avoid polyhedron separator
2683             {
2684               for (int idim=0; idim<dim; idim++)
2685                 {
2686                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2687                     {
2688                       elem_bb[idim*2] = coords[node*dim+idim] ;
2689                     }
2690                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2691                     {
2692                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2693                     }
2694                 }
2695             }
2696         }
2697       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2698         elems->pushBackSilent(ielem);
2699     }
2700   return elems.retn();
2701 }
2702
2703 /*!
2704  * Returns a type of a cell by its id.
2705  *  \param [in] cellId - the id of the cell of interest.
2706  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2707  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2708  */
2709 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2710 {
2711   const int *ptI=_nodal_connec_index->getConstPointer();
2712   const int *pt=_nodal_connec->getConstPointer();
2713   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2714     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2715   else
2716     {
2717       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2718       throw INTERP_KERNEL::Exception(oss.str().c_str());
2719     }
2720 }
2721
2722 /*!
2723  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2724  * This method does not throw exception if geometric type \a type is not in \a this.
2725  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2726  * The coordinates array is not considered here.
2727  *
2728  * \param [in] type the geometric type
2729  * \return cell ids in this having geometric type \a type.
2730  */
2731 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2732 {
2733   
2734   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2735   ret->alloc(0,1);
2736   checkConnectivityFullyDefined();
2737   int nbCells=getNumberOfCells();
2738   int mdim=getMeshDimension();
2739   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2740   if(mdim!=(int)cm.getDimension())
2741     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2742   const int *ptI=_nodal_connec_index->getConstPointer();
2743   const int *pt=_nodal_connec->getConstPointer();
2744   for(int i=0;i<nbCells;i++)
2745     {
2746       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2747         ret->pushBackSilent(i);
2748     }
2749   return ret.retn();
2750 }
2751
2752 /*!
2753  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2754  */
2755 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2756 {
2757   const int *ptI=_nodal_connec_index->getConstPointer();
2758   const int *pt=_nodal_connec->getConstPointer();
2759   int nbOfCells=getNumberOfCells();
2760   int ret=0;
2761   for(int i=0;i<nbOfCells;i++)
2762     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2763       ret++;
2764   return ret;
2765 }
2766
2767 /*!
2768  * Returns the nodal connectivity of a given cell.
2769  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2770  * all returned node ids can be used in getCoordinatesOfNode().
2771  *  \param [in] cellId - an id of the cell of interest.
2772  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2773  *         cleared before the appending.
2774  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2775  */
2776 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2777 {
2778   const int *ptI=_nodal_connec_index->getConstPointer();
2779   const int *pt=_nodal_connec->getConstPointer();
2780   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2781     if(*w>=0)
2782       conn.push_back(*w);
2783 }
2784
2785 std::string MEDCouplingUMesh::simpleRepr() const
2786 {
2787   static const char msg0[]="No coordinates specified !";
2788   std::ostringstream ret;
2789   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2790   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2791   int tmpp1,tmpp2;
2792   double tt=getTime(tmpp1,tmpp2);
2793   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2794   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2795   if(_mesh_dim>=-1)
2796     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2797   else
2798     { ret << " Mesh dimension has not been set or is invalid !"; }
2799   if(_coords!=0)
2800     {
2801       const int spaceDim=getSpaceDimension();
2802       ret << spaceDim << "\nInfo attached on space dimension : ";
2803       for(int i=0;i<spaceDim;i++)
2804         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2805       ret << "\n";
2806     }
2807   else
2808     ret << msg0 << "\n";
2809   ret << "Number of nodes : ";
2810   if(_coords!=0)
2811     ret << getNumberOfNodes() << "\n";
2812   else
2813     ret << msg0 << "\n";
2814   ret << "Number of cells : ";
2815   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2816     ret << getNumberOfCells() << "\n";
2817   else
2818     ret << "No connectivity specified !" << "\n";
2819   ret << "Cell types present : ";
2820   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2821     {
2822       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2823       ret << cm.getRepr() << " ";
2824     }
2825   ret << "\n";
2826   return ret.str();
2827 }
2828
2829 std::string MEDCouplingUMesh::advancedRepr() const
2830 {
2831   std::ostringstream ret;
2832   ret << simpleRepr();
2833   ret << "\nCoordinates array : \n___________________\n\n";
2834   if(_coords)
2835     _coords->reprWithoutNameStream(ret);
2836   else
2837     ret << "No array set !\n";
2838   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2839   reprConnectivityOfThisLL(ret);
2840   return ret.str();
2841 }
2842
2843 /*!
2844  * This method returns a C++ code that is a dump of \a this.
2845  * This method will throw if this is not fully defined.
2846  */
2847 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2848 {
2849   static const char coordsName[]="coords";
2850   static const char connName[]="conn";
2851   static const char connIName[]="connI";
2852   checkFullyDefined();
2853   std::ostringstream ret; ret << "// coordinates" << std::endl;
2854   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2855   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2856   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2857   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2858   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2859   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2860   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2861   return ret.str();
2862 }
2863
2864 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2865 {
2866   std::ostringstream ret;
2867   reprConnectivityOfThisLL(ret);
2868   return ret.str();
2869 }
2870
2871 /*!
2872  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2873  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2874  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2875  * some algos).
2876  * 
2877  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2878  * 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
2879  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2880  */
2881 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2882 {
2883   int mdim=getMeshDimension();
2884   if(mdim<0)
2885     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2886   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2888   bool needToCpyCT=true;
2889   if(!_nodal_connec)
2890     {
2891       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2892       needToCpyCT=false;
2893     }
2894   else
2895     {
2896       tmp1=_nodal_connec;
2897       tmp1->incrRef();
2898     }
2899   if(!_nodal_connec_index)
2900     {
2901       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2902       needToCpyCT=false;
2903     }
2904   else
2905     {
2906       tmp2=_nodal_connec_index;
2907       tmp2->incrRef();
2908     }
2909   ret->setConnectivity(tmp1,tmp2,false);
2910   if(needToCpyCT)
2911     ret->_types=_types;
2912   if(!_coords)
2913     {
2914       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2915       ret->setCoords(coords);
2916     }
2917   else
2918     ret->setCoords(_coords);
2919   return ret.retn();
2920 }
2921
2922 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2923 {
2924   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2925     {
2926       int nbOfCells=getNumberOfCells();
2927       const int *c=_nodal_connec->getConstPointer();
2928       const int *ci=_nodal_connec_index->getConstPointer();
2929       for(int i=0;i<nbOfCells;i++)
2930         {
2931           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2932           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2933           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2934           stream << "\n";
2935         }
2936     }
2937   else
2938     stream << "Connectivity not defined !\n";
2939 }
2940
2941 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2942 {
2943   const int *ptI=_nodal_connec_index->getConstPointer();
2944   const int *pt=_nodal_connec->getConstPointer();
2945   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2946     return ptI[cellId+1]-ptI[cellId]-1;
2947   else
2948     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2949 }
2950
2951 /*!
2952  * Returns types of cells of the specified part of \a this mesh.
2953  * This method avoids computing sub-mesh explicitely to get its types.
2954  *  \param [in] begin - an array of cell ids of interest.
2955  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2956  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2957  *         describing the cell types. 
2958  *  \throw If the coordinates array is not set.
2959  *  \throw If the nodal connectivity of cells is not defined.
2960  *  \sa getAllTypes()
2961  */
2962 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2963 {
2964   checkFullyDefined();
2965   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2966   const int *conn=_nodal_connec->getConstPointer();
2967   const int *connIndex=_nodal_connec_index->getConstPointer();
2968   for(const int *w=begin;w!=end;w++)
2969     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2970   return ret;
2971 }
2972
2973 /*!
2974  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2975  * a set of types of cells constituting \a this mesh. 
2976  * This method is for advanced users having prepared their connectivity before. For
2977  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2978  *  \param [in] conn - the nodal connectivity array. 
2979  *  \param [in] connIndex - the nodal connectivity index array.
2980  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2981  *         mesh is updated.
2982  */
2983 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2984 {
2985   DataArrayInt::SetArrayIn(conn,_nodal_connec);
2986   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2987   if(isComputingTypes)
2988     computeTypes();
2989   declareAsNew();
2990 }
2991
2992 /*!
2993  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2994  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2995  */
2996 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2997                                                                                  _nodal_connec(0),_nodal_connec_index(0),
2998                                                                                 _types(other._types)
2999 {
3000   if(other._nodal_connec)
3001     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3002   if(other._nodal_connec_index)
3003     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3004 }
3005
3006 MEDCouplingUMesh::~MEDCouplingUMesh()
3007 {
3008   if(_nodal_connec)
3009     _nodal_connec->decrRef();
3010   if(_nodal_connec_index)
3011     _nodal_connec_index->decrRef();
3012 }
3013
3014 /*!
3015  * Recomputes a set of cell types of \a this mesh. For more info see
3016  * \ref MEDCouplingUMeshNodalConnectivity.
3017  */
3018 void MEDCouplingUMesh::computeTypes()
3019 {
3020   if(_nodal_connec && _nodal_connec_index)
3021     {
3022       _types.clear();
3023       const int *conn=_nodal_connec->getConstPointer();
3024       const int *connIndex=_nodal_connec_index->getConstPointer();
3025       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3026       if (nbOfElem > 0)
3027         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3028           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3029     }
3030 }
3031
3032 /*!
3033  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3034  */
3035 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
3036 {
3037   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3038     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3039 }
3040
3041 /*!
3042  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3043  */
3044 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
3045 {
3046   if(!_nodal_connec_index || !_nodal_connec)
3047     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3048 }
3049
3050 /*!
3051  * Returns a number of cells constituting \a this mesh. 
3052  *  \return int - the number of cells in \a this mesh.
3053  *  \throw If the nodal connectivity of cells is not defined.
3054  */
3055 int MEDCouplingUMesh::getNumberOfCells() const
3056
3057   if(_nodal_connec_index)
3058     return _nodal_connec_index->getNumberOfTuples()-1;
3059   else
3060     if(_mesh_dim==-1)
3061       return 1;
3062     else
3063       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3064 }
3065
3066 /*!
3067  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3068  * mesh. For more info see \ref MEDCouplingMeshesPage.
3069  *  \return int - the dimension of \a this mesh.
3070  *  \throw If the mesh dimension is not defined using setMeshDimension().
3071  */
3072 int MEDCouplingUMesh::getMeshDimension() const
3073 {
3074   if(_mesh_dim<-1)
3075     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3076   return _mesh_dim;
3077 }
3078
3079 /*!
3080  * Returns a length of the nodal connectivity array.
3081  * This method is for test reason. Normally the integer returned is not useable by
3082  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3083  *  \return int - the length of the nodal connectivity array.
3084  */
3085 int MEDCouplingUMesh::getMeshLength() const
3086 {
3087   return _nodal_connec->getNbOfElems();
3088 }
3089
3090 /*!
3091  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3092  */
3093 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3094 {
3095   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3096   tinyInfo.push_back(getMeshDimension());
3097   tinyInfo.push_back(getNumberOfCells());
3098   if(_nodal_connec)
3099     tinyInfo.push_back(getMeshLength());
3100   else
3101     tinyInfo.push_back(-1);
3102 }
3103
3104 /*!
3105  * First step of unserialization process.
3106  */
3107 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3108 {
3109   return tinyInfo[6]<=0;
3110 }
3111
3112 /*!
3113  * Second step of serialization process.
3114  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3115  */
3116 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3117 {
3118   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3119   if(tinyInfo[5]!=-1)
3120     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3121 }
3122
3123 /*!
3124  * Third and final step of serialization process.
3125  */
3126 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3127 {
3128   MEDCouplingPointSet::serialize(a1,a2);
3129   if(getMeshDimension()>-1)
3130     {
3131       a1=DataArrayInt::New();
3132       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3133       int *ptA1=a1->getPointer();
3134       const int *conn=getNodalConnectivity()->getConstPointer();
3135       const int *index=getNodalConnectivityIndex()->getConstPointer();
3136       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3137       std::copy(conn,conn+getMeshLength(),ptA1);
3138     }
3139   else
3140     a1=0;
3141 }
3142
3143 /*!
3144  * Second and final unserialization process.
3145  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3146  */
3147 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3148 {
3149   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3150   setMeshDimension(tinyInfo[5]);
3151   if(tinyInfo[7]!=-1)
3152     {
3153       // Connectivity
3154       const int *recvBuffer=a1->getConstPointer();
3155       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3156       myConnecIndex->alloc(tinyInfo[6]+1,1);
3157       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3158       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3159       myConnec->alloc(tinyInfo[7],1);
3160       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3161       setConnectivity(myConnec, myConnecIndex);
3162     }
3163 }
3164
3165 /*!
3166  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3167  * CellIds are given using range specified by a start an end and step.
3168  */
3169 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3170 {
3171   checkFullyDefined();
3172   int ncell=getNumberOfCells();
3173   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3174   ret->_mesh_dim=_mesh_dim;
3175   ret->setCoords(_coords);
3176   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3177   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3178   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3179   int work=start;
3180   const int *conn=_nodal_connec->getConstPointer();
3181   const int *connIndex=_nodal_connec_index->getConstPointer();
3182   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3183     {
3184       if(work>=0 && work<ncell)
3185         {
3186           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3187         }
3188       else
3189         {
3190           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3191           throw INTERP_KERNEL::Exception(oss.str().c_str());
3192         }
3193     }
3194   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3195   int *newConnPtr=newConn->getPointer();
3196   std::set<INTERP_KERNEL::NormalizedCellType> types;
3197   work=start;
3198   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3199     {
3200       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3201       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3202     }
3203   ret->setConnectivity(newConn,newConnI,false);
3204   ret->_types=types;
3205   ret->copyTinyInfoFrom(this);
3206   return ret.retn();
3207 }
3208
3209 /*!
3210  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3211  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3212  * The return newly allocated mesh will share the same coordinates as \a this.
3213  */
3214 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3215 {
3216   checkFullyDefined();
3217   int ncell=getNumberOfCells();
3218   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3219   ret->_mesh_dim=_mesh_dim;
3220   ret->setCoords(_coords);
3221   std::size_t nbOfElemsRet=std::distance(begin,end);
3222   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3223   connIndexRet[0]=0;
3224   const int *conn=_nodal_connec->getConstPointer();
3225   const int *connIndex=_nodal_connec_index->getConstPointer();
3226   int newNbring=0;
3227   for(const int *work=begin;work!=end;work++,newNbring++)
3228     {
3229       if(*work>=0 && *work<ncell)
3230         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3231       else
3232         {
3233           free(connIndexRet);
3234           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3235           throw INTERP_KERNEL::Exception(oss.str().c_str());
3236         }
3237     }
3238   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3239   int *connRetWork=connRet;
3240   std::set<INTERP_KERNEL::NormalizedCellType> types;
3241   for(const int *work=begin;work!=end;work++)
3242     {
3243       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3244       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3245     }
3246   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3247   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3248   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3249   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3250   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3251   ret->_types=types;
3252   ret->copyTinyInfoFrom(this);
3253   return ret.retn();
3254 }
3255
3256 /*!
3257  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3258  * mesh.<br>
3259  * For 1D cells, the returned field contains lengths.<br>
3260  * For 2D cells, the returned field contains areas.<br>
3261  * For 3D cells, the returned field contains volumes.
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  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3265  *         and one time . The caller is to delete this field using decrRef() as it is no
3266  *         more needed.
3267  */
3268 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3269 {
3270   std::string name="MeasureOfMesh_";
3271   name+=getName();
3272   int nbelem=getNumberOfCells();
3273   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3274   field->setName(name.c_str());
3275   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3276   array->alloc(nbelem,1);
3277   double *area_vol=array->getPointer();
3278   field->setArray(array) ; array=0;
3279   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3280   field->synchronizeTimeWithMesh();
3281   if(getMeshDimension()!=-1)
3282     {
3283       int ipt;
3284       INTERP_KERNEL::NormalizedCellType type;
3285       int dim_space=getSpaceDimension();
3286       const double *coords=getCoords()->getConstPointer();
3287       const int *connec=getNodalConnectivity()->getConstPointer();
3288       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3289       for(int iel=0;iel<nbelem;iel++)
3290         {
3291           ipt=connec_index[iel];
3292           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3293           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);
3294         }
3295       if(isAbs)
3296         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3297     }
3298   else
3299     {
3300       area_vol[0]=std::numeric_limits<double>::max();
3301     }
3302   return field.retn();
3303 }
3304
3305 /*!
3306  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3307  * mesh.<br>
3308  * For 1D cells, the returned array contains lengths.<br>
3309  * For 2D cells, the returned array contains areas.<br>
3310  * For 3D cells, the returned array contains volumes.
3311  * This method avoids building explicitly a part of \a this mesh to perform the work.
3312  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3313  *         orientation, i.e. the volume is always positive.
3314  *  \param [in] begin - an array of cell ids of interest.
3315  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3316  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3317  *          delete this array using decrRef() as it is no more needed.
3318  * 
3319  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3320  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3321  *  \sa getMeasureField()
3322  */
3323 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3324 {
3325   std::string name="PartMeasureOfMesh_";
3326   name+=getName();
3327   int nbelem=(int)std::distance(begin,end);
3328   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3329   array->setName(name.c_str());
3330   array->alloc(nbelem,1);
3331   double *area_vol=array->getPointer();
3332   if(getMeshDimension()!=-1)
3333     {
3334       int ipt;
3335       INTERP_KERNEL::NormalizedCellType type;
3336       int dim_space=getSpaceDimension();
3337       const double *coords=getCoords()->getConstPointer();
3338       const int *connec=getNodalConnectivity()->getConstPointer();
3339       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3340       for(const int *iel=begin;iel!=end;iel++)
3341         {
3342           ipt=connec_index[*iel];
3343           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3344           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3345         }
3346       if(isAbs)
3347         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3348     }
3349   else
3350     {
3351       area_vol[0]=std::numeric_limits<double>::max();
3352     }
3353   return array.retn();
3354 }
3355
3356 /*!
3357  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3358  * \a this one. The returned field contains the dual cell volume for each corresponding
3359  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3360  *  the dual mesh in P1 sens of \a this.<br>
3361  * For 1D cells, the returned field contains lengths.<br>
3362  * For 2D cells, the returned field contains areas.<br>
3363  * For 3D cells, the returned field contains volumes.
3364  * This method is useful to check "P1*" conservative interpolators.
3365  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3366  *         orientation, i.e. the volume is always positive.
3367  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3368  *          nodes and one time. The caller is to delete this array using decrRef() as
3369  *          it is no more needed.
3370  */
3371 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3372 {
3373   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3374   std::string name="MeasureOnNodeOfMesh_";
3375   name+=getName();
3376   int nbNodes=getNumberOfNodes();
3377   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3378   double cst=1./((double)getMeshDimension()+1.);
3379   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3380   array->alloc(nbNodes,1);
3381   double *valsToFill=array->getPointer();
3382   std::fill(valsToFill,valsToFill+nbNodes,0.);
3383   const double *values=tmp->getArray()->getConstPointer();
3384   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3385   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3386   getReverseNodalConnectivity(da,daInd);
3387   const int *daPtr=da->getConstPointer();
3388   const int *daIPtr=daInd->getConstPointer();
3389   for(int i=0;i<nbNodes;i++)
3390     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3391       valsToFill[i]+=cst*values[*cell];
3392   ret->setMesh(this);
3393   ret->setArray(array);
3394   return ret.retn();
3395 }
3396
3397 /*!
3398  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3399  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3400  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3401  * and are normalized.
3402  * <br> \a this can be either 
3403  * - a  2D mesh in 2D or 3D space or 
3404  * - an 1D mesh in 2D space.
3405  * 
3406  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3407  *          cells and one time. The caller is to delete this field using decrRef() as
3408  *          it is no more needed.
3409  *  \throw If the nodal connectivity of cells is not defined.
3410  *  \throw If the coordinates array is not set.
3411  *  \throw If the mesh dimension is not set.
3412  *  \throw If the mesh and space dimension is not as specified above.
3413  */
3414 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3415 {
3416   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3417     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3418   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3419   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3420   int nbOfCells=getNumberOfCells();
3421   int nbComp=getMeshDimension()+1;
3422   array->alloc(nbOfCells,nbComp);
3423   double *vals=array->getPointer();
3424   const int *connI=_nodal_connec_index->getConstPointer();
3425   const int *conn=_nodal_connec->getConstPointer();
3426   const double *coords=_coords->getConstPointer();
3427   if(getMeshDimension()==2)
3428     {
3429       if(getSpaceDimension()==3)
3430         {
3431           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3432           const double *locPtr=loc->getConstPointer();
3433           for(int i=0;i<nbOfCells;i++,vals+=3)
3434             {
3435               int offset=connI[i];
3436               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3437               double n=INTERP_KERNEL::norm<3>(vals);
3438               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3439             }
3440         }
3441       else
3442         {
3443           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3444           const double *isAbsPtr=isAbs->getArray()->begin();
3445           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3446             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3447         }
3448     }
3449   else//meshdimension==1
3450     {
3451       double tmp[2];
3452       for(int i=0;i<nbOfCells;i++)
3453         {
3454           int offset=connI[i];
3455           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3456           double n=INTERP_KERNEL::norm<2>(tmp);
3457           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3458           *vals++=-tmp[1];
3459           *vals++=tmp[0];
3460         }
3461     }
3462   ret->setArray(array);
3463   ret->setMesh(this);
3464   ret->synchronizeTimeWithSupport();
3465   return ret.retn();
3466 }
3467
3468 /*!
3469  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3470  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3471  * and are normalized.
3472  * <br> \a this can be either 
3473  * - a  2D mesh in 2D or 3D space or 
3474  * - an 1D mesh in 2D space.
3475  * 
3476  * This method avoids building explicitly a part of \a this mesh to perform the work.
3477  *  \param [in] begin - an array of cell ids of interest.
3478  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3479  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3480  *          cells and one time. The caller is to delete this field using decrRef() as
3481  *          it is no more needed.
3482  *  \throw If the nodal connectivity of cells is not defined.
3483  *  \throw If the coordinates array is not set.
3484  *  \throw If the mesh dimension is not set.
3485  *  \throw If the mesh and space dimension is not as specified above.
3486  *  \sa buildOrthogonalField()
3487  *
3488  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3489  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3490  */
3491 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3492 {
3493   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3494     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3495   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3496   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3497   std::size_t nbelems=std::distance(begin,end);
3498   int nbComp=getMeshDimension()+1;
3499   array->alloc((int)nbelems,nbComp);
3500   double *vals=array->getPointer();
3501   const int *connI=_nodal_connec_index->getConstPointer();
3502   const int *conn=_nodal_connec->getConstPointer();
3503   const double *coords=_coords->getConstPointer();
3504   if(getMeshDimension()==2)
3505     {
3506       if(getSpaceDimension()==3)
3507         {
3508           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3509           const double *locPtr=loc->getConstPointer();
3510           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3511             {
3512               int offset=connI[*i];
3513               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3514               double n=INTERP_KERNEL::norm<3>(vals);
3515               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3516             }
3517         }
3518       else
3519         {
3520           for(std::size_t i=0;i<nbelems;i++)
3521             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3522         }
3523     }
3524   else//meshdimension==1
3525     {
3526       double tmp[2];
3527       for(const int *i=begin;i!=end;i++)
3528         {
3529           int offset=connI[*i];
3530           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3531           double n=INTERP_KERNEL::norm<2>(tmp);
3532           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3533           *vals++=-tmp[1];
3534           *vals++=tmp[0];
3535         }
3536     }
3537   ret->setArray(array);
3538   ret->setMesh(this);
3539   ret->synchronizeTimeWithSupport();
3540   return ret.retn();
3541 }
3542
3543 /*!
3544  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3545  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3546  * and are \b not normalized.
3547  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3548  *          cells and one time. The caller is to delete this field using decrRef() as
3549  *          it is no more needed.
3550  *  \throw If the nodal connectivity of cells is not defined.
3551  *  \throw If the coordinates array is not set.
3552  *  \throw If \a this->getMeshDimension() != 1.
3553  *  \throw If \a this mesh includes cells of type other than SEG2.
3554  */
3555 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3556 {
3557    if(getMeshDimension()!=1)
3558     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3559    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3560      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3561    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3562    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3563    int nbOfCells=getNumberOfCells();
3564    int spaceDim=getSpaceDimension();
3565    array->alloc(nbOfCells,spaceDim);
3566    double *pt=array->getPointer();
3567    const double *coo=getCoords()->getConstPointer();
3568    std::vector<int> conn;
3569    conn.reserve(2);
3570    for(int i=0;i<nbOfCells;i++)
3571      {
3572        conn.resize(0);
3573        getNodeIdsOfCell(i,conn);
3574        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3575      }
3576    ret->setArray(array);
3577    ret->setMesh(this);
3578    ret->synchronizeTimeWithSupport();
3579    return ret.retn();   
3580 }
3581
3582 /*!
3583  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3584  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3585  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3586  * from. If a result face is shared by two 3D cells, then the face in included twice in
3587  * the result mesh.
3588  *  \param [in] origin - 3 components of a point defining location of the plane.
3589  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3590  *         must be greater than 1e-6.
3591  *  \param [in] eps - half-thickness of the plane.
3592  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3593  *         producing correspondent 2D cells. The caller is to delete this array
3594  *         using decrRef() as it is no more needed.
3595  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3596  *         not share the node coordinates array with \a this mesh. The caller is to
3597  *         delete this mesh using decrRef() as it is no more needed.  
3598  *  \throw If the coordinates array is not set.
3599  *  \throw If the nodal connectivity of cells is not defined.
3600  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3601  *  \throw If magnitude of \a vec is less than 1e-6.
3602  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3603  *  \throw If \a this includes quadratic cells.
3604  */
3605 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3606 {
3607   checkFullyDefined();
3608   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3609     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3610   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3611   if(candidates->empty())
3612     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3613   std::vector<int> nodes;
3614   DataArrayInt *cellIds1D=0;
3615   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3616   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3617   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3618   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3619   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3620   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3621   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3622   revDesc2=0; revDescIndx2=0;
3623   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3624   revDesc1=0; revDescIndx1=0;
3625   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3626   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3627   //
3628   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3629   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3630     cut3DCurve[*it]=-1;
3631   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3632   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3633   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3634                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3635                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3636   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3637   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3638   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3639   if(cellIds2->empty())
3640     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3641   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3642   ret->setCoords(mDesc1->getCoords());
3643   ret->setConnectivity(conn,connI,true);
3644   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3645   return ret.retn();
3646 }
3647
3648 /*!
3649  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3650 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
3651 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3652 the result mesh.
3653  *  \param [in] origin - 3 components of a point defining location of the plane.
3654  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3655  *         must be greater than 1e-6.
3656  *  \param [in] eps - half-thickness of the plane.
3657  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3658  *         producing correspondent segments. The caller is to delete this array
3659  *         using decrRef() as it is no more needed.
3660  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3661  *         mesh in 3D space. This mesh does not share the node coordinates array with
3662  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3663  *         no more needed. 
3664  *  \throw If the coordinates array is not set.
3665  *  \throw If the nodal connectivity of cells is not defined.
3666  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3667  *  \throw If magnitude of \a vec is less than 1e-6.
3668  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3669  *  \throw If \a this includes quadratic cells.
3670  */
3671 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3672 {
3673   checkFullyDefined();
3674   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3675     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3676   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3677   if(candidates->empty())
3678     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3679   std::vector<int> nodes;
3680   DataArrayInt *cellIds1D=0;
3681   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3682   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3683   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3684   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3685   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3686   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3687   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3688   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3689   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3690   //
3691   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3692   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3693     cut3DCurve[*it]=-1;
3694   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3695   int ncellsSub=subMesh->getNumberOfCells();
3696   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3697   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3698                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3699                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3700   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3701   conn->alloc(0,1);
3702   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3703   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3704   for(int i=0;i<ncellsSub;i++)
3705     {
3706       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3707         {
3708           if(cut3DSurf[i].first!=-2)
3709             {
3710               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3711               connI->pushBackSilent(conn->getNumberOfTuples());
3712               cellIds2->pushBackSilent(i);
3713             }
3714           else
3715             {
3716               int cellId3DSurf=cut3DSurf[i].second;
3717               int offset=nodalI[cellId3DSurf]+1;
3718               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3719               for(int j=0;j<nbOfEdges;j++)
3720                 {
3721                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3722                   connI->pushBackSilent(conn->getNumberOfTuples());
3723                   cellIds2->pushBackSilent(cellId3DSurf);
3724                 }
3725             }
3726         }
3727     }
3728   if(cellIds2->empty())
3729     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3730   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3731   ret->setCoords(mDesc1->getCoords());
3732   ret->setConnectivity(conn,connI,true);
3733   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3734   return ret.retn();
3735 }
3736
3737 /*!
3738  * Finds cells whose bounding boxes intersect a given plane.
3739  *  \param [in] origin - 3 components of a point defining location of the plane.
3740  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3741  *         must be greater than 1e-6.
3742  *  \param [in] eps - half-thickness of the plane.
3743  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3744  *         cells. The caller is to delete this array using decrRef() as it is no more
3745  *         needed.
3746  *  \throw If the coordinates array is not set.
3747  *  \throw If the nodal connectivity of cells is not defined.
3748  *  \throw If \a this->getSpaceDimension() != 3.
3749  *  \throw If magnitude of \a vec is less than 1e-6.
3750  *  \sa buildSlice3D()
3751  */
3752 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3753 {
3754   checkFullyDefined();
3755   if(getSpaceDimension()!=3)
3756     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3757   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3758   if(normm<1e-6)
3759     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3760   double vec2[3];
3761   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3762   double angle=acos(vec[2]/normm);
3763   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3764   double bbox[6];
3765   if(angle>eps)
3766     {
3767       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3768       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3769       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3770       mw->setCoords(coo);
3771       mw->getBoundingBox(bbox);
3772       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3773       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3774     }
3775   else
3776     {
3777       getBoundingBox(bbox);
3778       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3779       cellIds=getCellsInBoundingBox(bbox,eps);
3780     }
3781   return cellIds.retn();
3782 }
3783
3784 /*!
3785  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3786  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3787  * No consideration of coordinate is done by this method.
3788  * 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)
3789  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3790  */
3791 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3792 {
3793   if(getMeshDimension()!=1)
3794     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3795   int nbCells=getNumberOfCells();
3796   if(nbCells<1)
3797     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3798   const int *connI=_nodal_connec_index->getConstPointer();
3799   const int *conn=_nodal_connec->getConstPointer();
3800   int ref=conn[connI[0]+2];
3801   for(int i=1;i<nbCells;i++)
3802     {
3803       if(conn[connI[i]+1]!=ref)
3804         return false;
3805       ref=conn[connI[i]+2];
3806     }
3807   return true;
3808 }
3809
3810 /*!
3811  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3812  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3813  * \param pt reference point of the line
3814  * \param v normalized director vector of the line
3815  * \param eps max precision before throwing an exception
3816  * \param res output of size this->getNumberOfCells
3817  */
3818 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3819 {
3820   if(getMeshDimension()!=1)
3821     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3822    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3823      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3824    if(getSpaceDimension()!=3)
3825      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3826    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3827    const double *fPtr=f->getArray()->getConstPointer();
3828    double tmp[3];
3829    for(int i=0;i<getNumberOfCells();i++)
3830      {
3831        const double *tmp1=fPtr+3*i;
3832        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3833        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3834        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3835        double n1=INTERP_KERNEL::norm<3>(tmp);
3836        n1/=INTERP_KERNEL::norm<3>(tmp1);
3837        if(n1>eps)
3838          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3839      }
3840    const double *coo=getCoords()->getConstPointer();
3841    for(int i=0;i<getNumberOfNodes();i++)
3842      {
3843        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3844        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3845        res[i]=std::accumulate(tmp,tmp+3,0.);
3846      }
3847 }
3848
3849 /*!
3850  * 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. 
3851  * \a this is expected to be a mesh so that its space dimension is equal to its
3852  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3853  * 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).
3854  
3855  * 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
3856  * 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).
3857  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3858  *
3859  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3860  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3861  *
3862  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3863  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3864  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3865  * \return the positive value of the distance.
3866  * \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
3867  * dimension - 1.
3868  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3869  */
3870 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
3871 {
3872   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3873   if(meshDim!=spaceDim-1)
3874     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3875   if(meshDim!=2 && meshDim!=1)
3876     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3877   checkFullyDefined();
3878   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3879     { 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()); }
3880   DataArrayInt *ret1=0;
3881   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3882   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3883   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3884   cellId=*ret1Safe->begin();
3885   return *ret0->begin();
3886 }
3887
3888 /*!
3889  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3890  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3891  * 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
3892  * 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).
3893  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3894  * 
3895  * \a this is expected to be a mesh so that its space dimension is equal to its
3896  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3897  * 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).
3898  *
3899  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3900  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3901  *
3902  * \param [in] pts the list of points in which each tuple represents a point
3903  * \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.
3904  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3905  * \throw if number of components of \a pts is not equal to the space dimension.
3906  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3907  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3908  */
3909 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
3910 {
3911   if(!pts)
3912     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3913   pts->checkAllocated();
3914   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3915   if(meshDim!=spaceDim-1)
3916     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3917   if(meshDim!=2 && meshDim!=1)
3918     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3919   if(pts->getNumberOfComponents()!=spaceDim)
3920     {
3921       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3922       throw INTERP_KERNEL::Exception(oss.str().c_str());
3923     }
3924   checkFullyDefined();
3925   int nbCells=getNumberOfCells();
3926   if(nbCells==0)
3927     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3928   int nbOfPts=pts->getNumberOfTuples();
3929   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3930   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3931   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3932   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3933   std::vector<double> bbox;
3934   getBoundingBoxForBBTree(bbox);
3935   switch(spaceDim)
3936     {
3937     case 3:
3938       {
3939         BBTreeDst<3> myTree(&bbox[0],0,0,nbCells);
3940         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3941           {
3942             double x=std::numeric_limits<double>::max();
3943             std::vector<int> elems;
3944             myTree.getMinDistanceOfMax(ptsPtr,x);
3945             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3946             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3947           }
3948         break;
3949       }
3950     case 2:
3951       {
3952         BBTreeDst<2> myTree(&bbox[0],0,0,nbCells);
3953         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3954           {
3955             double x=std::numeric_limits<double>::max();
3956             std::vector<int> elems;
3957             myTree.getMinDistanceOfMax(ptsPtr,x);
3958             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3959             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3960           }
3961         break;
3962       }
3963     default:
3964       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3965     }
3966   cellIds=ret1.retn();
3967   return ret0.retn();
3968 }
3969
3970 /*!
3971  * \param [in] pt the start pointer (included) of the coordinates of the point
3972  * \param [in] cellIdsBg the start pointer (included) of cellIds
3973  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3974  * \param [in] nc nodal connectivity
3975  * \param [in] ncI nodal connectivity index
3976  * \param [in,out] ret0 the min distance between \a this and the external input point
3977  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3978  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3979  */
3980 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)
3981 {
3982   cellId=-1;
3983   ret0=std::numeric_limits<double>::max();
3984   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3985     {
3986       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3987         {
3988         case INTERP_KERNEL::NORM_TRI3:
3989           {
3990             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3991             if(tmp<ret0)
3992               { ret0=tmp; cellId=*zeCell; }
3993             break;
3994           }
3995         case INTERP_KERNEL::NORM_QUAD4:
3996         case INTERP_KERNEL::NORM_POLYGON:
3997           {
3998             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3999             if(tmp<ret0)
4000               { ret0=tmp; cellId=*zeCell; }
4001             break;
4002           }
4003         default:
4004           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4005         }
4006     }
4007 }
4008
4009 /*!
4010  * \param [in] pt the start pointer (included) of the coordinates of the point
4011  * \param [in] cellIdsBg the start pointer (included) of cellIds
4012  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4013  * \param [in] nc nodal connectivity
4014  * \param [in] ncI nodal connectivity index
4015  * \param [in,out] ret0 the min distance between \a this and the external input point
4016  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4017  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4018  */
4019 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)
4020 {
4021   cellId=-1;
4022   ret0=std::numeric_limits<double>::max();
4023   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4024     {
4025        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4026         {
4027         case INTERP_KERNEL::NORM_SEG2:
4028           {
4029             std::size_t uselessEntry=0;
4030             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4031             tmp=sqrt(tmp);
4032             if(tmp<ret0)
4033               { ret0=tmp; cellId=*zeCell; }
4034             break;
4035           }
4036         default:
4037           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4038         }
4039     }
4040 }
4041
4042 /*!
4043  * Finds cells in contact with a ball (i.e. a point with precision). 
4044  * \warning This method is suitable if the caller intends to evaluate only one
4045  *          point, for more points getCellsContainingPoints() is recommended as it is
4046  *          faster. 
4047  *  \param [in] pos - array of coordinates of the ball central point.
4048  *  \param [in] eps - ball radius.
4049  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4050  *         if there are no such cells.
4051  *  \throw If the coordinates array is not set.
4052  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4053  */
4054 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4055 {
4056   std::vector<int> elts;
4057   getCellsContainingPoint(pos,eps,elts);
4058   if(elts.empty())
4059     return -1;
4060   return elts.front();
4061 }
4062
4063 /*!
4064  * Finds cells in contact with a ball (i.e. a point with precision).
4065  * \warning This method is suitable if the caller intends to evaluate only one
4066  *          point, for more points getCellsContainingPoints() is recommended as it is
4067  *          faster. 
4068  *  \param [in] pos - array of coordinates of the ball central point.
4069  *  \param [in] eps - ball radius.
4070  *  \param [in,out] elts - vector returning ids of the found cells. It is cleared
4071  *         before inserting ids.
4072  *  \throw If the coordinates array is not set.
4073  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4074  *
4075  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4076  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4077  */
4078 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4079 {
4080   std::vector<int> eltsIndex;
4081   getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
4082 }
4083
4084 /// @cond INTERNAL
4085
4086 namespace ParaMEDMEM
4087 {
4088   template<const int SPACEDIMM>
4089   class DummyClsMCUG
4090   {
4091   public:
4092     static const int MY_SPACEDIM=SPACEDIMM;
4093     static const int MY_MESHDIM=8;
4094     typedef int MyConnType;
4095     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4096     // begin
4097     // useless, but for windows compilation ...
4098     const double* getCoordinatesPtr() const { return 0; }
4099     const int* getConnectivityPtr() const { return 0; }
4100     const int* getConnectivityIndexPtr() const { return 0; }
4101     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4102     // end
4103   };
4104
4105   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4106   {
4107     INTERP_KERNEL::Edge *ret=0;
4108     switch(typ)
4109       {
4110       case INTERP_KERNEL::NORM_SEG2:
4111         {
4112           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4113           break;
4114         }
4115       case INTERP_KERNEL::NORM_SEG3:
4116         {
4117           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4118           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4119           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4120           bool colinearity=inters.areColinears();
4121           delete e1; delete e2;
4122           if(colinearity)
4123             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4124           else
4125             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4126           mapp2[bg[2]].second=false;
4127           break;
4128         }
4129       default:
4130         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4131       }
4132     return ret;
4133   }
4134
4135   /*!
4136    * 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'.
4137    * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4138    * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4139    */
4140   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4141   {
4142     mapp.clear();
4143     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.
4144     const double *coo=mDesc->getCoords()->getConstPointer();
4145     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4146     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4147     std::set<int> s;
4148     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4149       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4150     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4151       {
4152         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4153         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4154       }
4155     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4156     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4157       {
4158         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4159         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4160       }
4161     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4162       {
4163         if((*it2).second.second)
4164           mapp[(*it2).second.first]=(*it2).first;
4165         ((*it2).second.first)->decrRef();
4166       }
4167     return ret;
4168   }
4169
4170   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4171   {
4172     if(nodeId>=offset2)
4173       {
4174         int locId=nodeId-offset2;
4175         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4176       }
4177     if(nodeId>=offset1)
4178       {
4179         int locId=nodeId-offset1;
4180         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4181       }
4182     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4183   }
4184
4185   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4186                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4187                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4188   {
4189     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4190       {
4191         int eltId1=abs(*desc1)-1;
4192         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4193           {
4194             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4195             if(it==mappRev.end())
4196               {
4197                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4198                 mapp[node]=*it1;
4199                 mappRev[*it1]=node;
4200               }
4201           }
4202       }
4203   }
4204 }
4205
4206 /// @endcond
4207
4208 template<int SPACEDIM>
4209 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4210                                                    double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4211 {
4212   std::vector<double> bbox;
4213   eltsIndex.resize(nbOfPoints+1);
4214   eltsIndex[0]=0;
4215   elts.clear();
4216   getBoundingBoxForBBTree(bbox);
4217   int nbOfCells=getNumberOfCells();
4218   const int *conn=_nodal_connec->getConstPointer();
4219   const int *connI=_nodal_connec_index->getConstPointer();
4220   double bb[2*SPACEDIM];
4221   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4222   for(int i=0;i<nbOfPoints;i++)
4223     {
4224       eltsIndex[i+1]=eltsIndex[i];
4225       for(int j=0;j<SPACEDIM;j++)
4226         {
4227           bb[2*j]=pos[SPACEDIM*i+j];
4228           bb[2*j+1]=pos[SPACEDIM*i+j];
4229         }
4230       std::vector<int> candidates;
4231       myTree.getIntersectingElems(bb,candidates);
4232       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4233         {
4234           int sz=connI[(*iter)+1]-connI[*iter]-1;
4235           if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4236                                                                                                (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4237                                                                                                coords,conn+connI[*iter]+1,sz,eps))
4238             {
4239               eltsIndex[i+1]++;
4240               elts.push_back(*iter);
4241             }
4242         }
4243     }
4244 }
4245 /*!
4246  * Finds cells in contact with several balls (i.e. points with precision).
4247  * This method is an extension of getCellContainingPoint() and
4248  * getCellsContainingPoint() for the case of multiple points.
4249  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4250  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4251  *         this->getSpaceDimension() * \a nbOfPoints 
4252  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4253  *  \param [in] eps - radius of balls (i.e. the precision).
4254  *  \param [in,out] elts - vector returning ids of found cells.
4255  *  \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4256  *         dividing cell ids in \a elts into groups each referring to one
4257  *         point. Its every element (except the last one) is an index pointing to the
4258  *         first id of a group of cells. For example cells in contact with the *i*-th
4259  *         point are described by following range of indices:
4260  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4261  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4262  *         Number of cells in contact with the *i*-th point is
4263  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4264  *  \throw If the coordinates array is not set.
4265  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4266  *
4267  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4268  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4269  */
4270 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4271                                                 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4272 {
4273   int spaceDim=getSpaceDimension();
4274   int mDim=getMeshDimension();
4275   if(spaceDim==3)
4276     {
4277       if(mDim==3)
4278         {
4279           const double *coords=_coords->getConstPointer();
4280           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4281         }
4282       /*else if(mDim==2)
4283         {
4284           
4285         }*/
4286       else
4287         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4288     }
4289   else if(spaceDim==2)
4290     {
4291       if(mDim==2)
4292         {
4293           const double *coords=_coords->getConstPointer();
4294           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4295         }
4296       else
4297         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4298     }
4299   else if(spaceDim==1)
4300     {
4301       if(mDim==1)
4302         {
4303           const double *coords=_coords->getConstPointer();
4304           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4305         }
4306       else
4307         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4308     }
4309   else
4310     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4311 }
4312
4313 /*!
4314  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4315  * least two its edges intersect each other anywhere except their extremities. An
4316  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4317  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4318  *         cleared before filling in.
4319  *  \param [in] eps - precision.
4320  *  \throw If \a this->getMeshDimension() != 2.
4321  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4322  */
4323 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4324 {
4325   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4326   if(getMeshDimension()!=2)
4327     throw INTERP_KERNEL::Exception(msg);
4328   int spaceDim=getSpaceDimension();
4329   if(spaceDim!=2 && spaceDim!=3)
4330     throw INTERP_KERNEL::Exception(msg);
4331   const int *conn=_nodal_connec->getConstPointer();
4332   const int *connI=_nodal_connec_index->getConstPointer();
4333   int nbOfCells=getNumberOfCells();
4334   std::vector<double> cell2DinS2;
4335   for(int i=0;i<nbOfCells;i++)
4336     {
4337       int offset=connI[i];
4338       int nbOfNodesForCell=connI[i+1]-offset-1;
4339       if(nbOfNodesForCell<=3)
4340         continue;
4341       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4342       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4343       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4344         cells.push_back(i);
4345       cell2DinS2.clear();
4346     }
4347 }
4348
4349 /*!
4350  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4351  *
4352  * 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.
4353  * 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.
4354  * 
4355  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4356  * This convex envelop is computed using Jarvis march algorithm.
4357  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4358  * 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)
4359  * 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.
4360  *
4361  * \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.
4362  */
4363 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4364 {
4365   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4366     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4367   checkFullyDefined();
4368   const double *coords=getCoords()->getConstPointer();
4369   int nbOfCells=getNumberOfCells();
4370   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4371   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4372   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4373   int *workIndexOut=nodalConnecIndexOut->getPointer();
4374   *workIndexOut=0;
4375   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4376   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4377   std::set<INTERP_KERNEL::NormalizedCellType> types;
4378   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4379   isChanged->alloc(0,1);
4380   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4381     {
4382       int pos=nodalConnecOut->getNumberOfTuples();
4383       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4384         isChanged->pushBackSilent(i);
4385       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4386       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4387     }
4388   if(isChanged->empty())
4389     return 0;
4390   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4391   _types=types;
4392   return isChanged.retn();
4393 }
4394
4395 /*!
4396  * This method is \b NOT const because it can modify \a this.
4397  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4398  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4399  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4400  * \b 1 for translation and rotation around point of 'mesh1D'.
4401  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4402  */
4403 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4404 {
4405   checkFullyDefined();
4406   mesh1D->checkFullyDefined();
4407   if(!mesh1D->isContiguous1D())
4408     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4409   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4410     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4411   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4412     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4413   if(mesh1D->getMeshDimension()!=1)
4414     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4415   bool isQuad=false;
4416   if(isPresenceOfQuadratic())
4417     {
4418       if(mesh1D->isFullyQuadratic())
4419         isQuad=true;
4420       else
4421         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4422     }
4423   zipCoords();
4424   int oldNbOfNodes=getNumberOfNodes();
4425   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4426   switch(policy)
4427     {
4428     case 0:
4429       {
4430         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4431         break;
4432       }
4433     case 1:
4434       {
4435         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4436         break;
4437       }
4438     default:
4439       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4440     }
4441   setCoords(newCoords);
4442   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4443   updateTime();
4444   return ret.retn();
4445 }
4446
4447 /*!
4448  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4449  * If it is not the case an exception will be thrown.
4450  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4451  * intersection of plane defined by ('origin','vec').
4452  * This method has one in/out parameter : 'cut3DCurve'.
4453  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4454  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4455  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4456  * This method will throw an exception if \a this contains a non linear segment.
4457  */
4458 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4459 {
4460   checkFullyDefined();
4461   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4462     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4463   int ncells=getNumberOfCells();
4464   int nnodes=getNumberOfNodes();
4465   double vec2[3],vec3[3],vec4[3];
4466   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4467   if(normm<1e-6)
4468     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4469   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4470   const int *conn=_nodal_connec->getConstPointer();
4471   const int *connI=_nodal_connec_index->getConstPointer();
4472   const double *coo=_coords->getConstPointer();
4473   std::vector<double> addCoo;
4474   for(int i=0;i<ncells;i++)
4475     {
4476       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4477         {
4478           if(cut3DCurve[i]==-2)
4479             {
4480               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4481               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];
4482               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4483               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4484               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4485                 {
4486                   const double *st2=coo+3*st;
4487                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4488                   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]));
4489                   if(pos>eps && pos<1-eps)
4490                     {
4491                       int nNode=((int)addCoo.size())/3;
4492                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4493                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4494                       cut3DCurve[i]=nnodes+nNode;
4495                     }
4496                 }
4497             }
4498         }
4499       else
4500         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4501     }
4502   if(!addCoo.empty())
4503     {
4504       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4505       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4506       coo2->alloc(newNbOfNodes,3);
4507       double *tmp=coo2->getPointer();
4508       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4509       std::copy(addCoo.begin(),addCoo.end(),tmp);
4510       DataArrayDouble::SetArrayIn(coo2,_coords);
4511     }
4512 }
4513
4514 /*!
4515  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4516  * \param mesh1D is the input 1D mesh used for translation computation.
4517  * \return newCoords new coords filled by this method. 
4518  */
4519 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4520 {
4521   int oldNbOfNodes=getNumberOfNodes();
4522   int nbOf1DCells=mesh1D->getNumberOfCells();
4523   int spaceDim=getSpaceDimension();
4524   DataArrayDouble *ret=DataArrayDouble::New();
4525   std::vector<bool> isQuads;
4526   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4527   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4528   double *retPtr=ret->getPointer();
4529   const double *coords=getCoords()->getConstPointer();
4530   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4531   std::vector<int> v;
4532   std::vector<double> c;
4533   double vec[3];
4534   v.reserve(3);
4535   c.reserve(6);
4536   for(int i=0;i<nbOf1DCells;i++)
4537     {
4538       v.resize(0);
4539       mesh1D->getNodeIdsOfCell(i,v);
4540       c.resize(0);
4541       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4542       mesh1D->getCoordinatesOfNode(v[0],c);
4543       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4544       for(int j=0;j<oldNbOfNodes;j++)
4545         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4546       if(isQuad)
4547         {
4548           c.resize(0);
4549           mesh1D->getCoordinatesOfNode(v[1],c);
4550           mesh1D->getCoordinatesOfNode(v[0],c);
4551           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4552           for(int j=0;j<oldNbOfNodes;j++)
4553             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4554         }
4555     }
4556   ret->copyStringInfoFrom(*getCoords());
4557   return ret;
4558 }
4559
4560 /*!
4561  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4562  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4563  * \return newCoords new coords filled by this method. 
4564  */
4565 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4566 {
4567   if(mesh1D->getSpaceDimension()==2)
4568     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4569   if(mesh1D->getSpaceDimension()==3)
4570     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4571   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4572 }
4573
4574 /*!
4575  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4576  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4577  * \return newCoords new coords filled by this method. 
4578  */
4579 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4580 {
4581   if(isQuad)
4582     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4583   int oldNbOfNodes=getNumberOfNodes();
4584   int nbOf1DCells=mesh1D->getNumberOfCells();
4585   if(nbOf1DCells<2)
4586     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4587   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4588   int nbOfLevsInVec=nbOf1DCells+1;
4589   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4590   double *retPtr=ret->getPointer();
4591   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4592   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4593   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4594   tmp->setCoords(tmp2);
4595   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4596   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4597   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4598   for(int i=1;i<nbOfLevsInVec;i++)
4599     {
4600       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4601       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4602       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4603       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4604       tmp->translate(vec);
4605       double tmp3[2],radius,alpha,alpha0;
4606       const double *p0=i+1<nbOfLevsInVec?begin:third;
4607       const double *p1=i+1<nbOfLevsInVec?end:begin;
4608       const double *p2=i+1<nbOfLevsInVec?third:end;
4609       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4610       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]);
4611       double angle=acos(cosangle/(radius*radius));
4612       tmp->rotate(end,0,angle);
4613       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4614     }
4615   return ret.retn();
4616 }
4617
4618 /*!
4619  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4620  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4621  * \return newCoords new coords filled by this method. 
4622  */
4623 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4624 {
4625   if(isQuad)
4626     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4627   int oldNbOfNodes=getNumberOfNodes();
4628   int nbOf1DCells=mesh1D->getNumberOfCells();
4629   if(nbOf1DCells<2)
4630     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4631   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4632   int nbOfLevsInVec=nbOf1DCells+1;
4633   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4634   double *retPtr=ret->getPointer();
4635   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4636   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4637   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4638   tmp->setCoords(tmp2);
4639   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4640   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4641   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4642   for(int i=1;i<nbOfLevsInVec;i++)
4643     {
4644       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4645       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4646       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4647       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4648       tmp->translate(vec);
4649       double tmp3[2],radius,alpha,alpha0;
4650       const double *p0=i+1<nbOfLevsInVec?begin:third;
4651       const double *p1=i+1<nbOfLevsInVec?end:begin;
4652       const double *p2=i+1<nbOfLevsInVec?third:end;
4653       double vecPlane[3]={
4654         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4655         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4656         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4657       };
4658       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4659       if(norm>1.e-7)
4660         {
4661           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4662           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4663           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4664           double s2=norm2;
4665           double c2=cos(asin(s2));
4666           double m[3][3]={
4667             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4668             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4669             {-vec2[1]*s2, vec2[0]*s2, c2}
4670           };
4671           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]};
4672           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]};
4673           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]};
4674           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4675           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]);
4676           double angle=acos(cosangle/(radius*radius));
4677           tmp->rotate(end,vecPlane,angle);
4678           
4679         }
4680       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4681     }
4682   return ret.retn();
4683 }
4684
4685 /*!
4686  * This method is private because not easy to use for end user. This method is const contrary to
4687  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4688  * the coords sorted slice by slice.
4689  * \param isQuad specifies presence of quadratic cells.
4690  */
4691 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4692 {
4693   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4694   int nbOf2DCells=getNumberOfCells();
4695   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4696   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4697   const int *conn=_nodal_connec->getConstPointer();
4698   const int *connI=_nodal_connec_index->getConstPointer();
4699   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4700   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4701   newConnI->alloc(nbOf3DCells+1,1);
4702   int *newConnIPtr=newConnI->getPointer();
4703   *newConnIPtr++=0;
4704   std::vector<int> newc;
4705   for(int j=0;j<nbOf2DCells;j++)
4706     {
4707       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4708       *newConnIPtr++=(int)newc.size();
4709     }
4710   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4711   int *newConnPtr=newConn->getPointer();
4712   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4713   newConnIPtr=newConnI->getPointer();
4714   for(int iz=0;iz<nbOf1DCells;iz++)
4715     {
4716       if(iz!=0)
4717         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4718       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4719         {
4720           int icell=(int)(iter-newc.begin());
4721           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4722             {
4723               if(*iter!=-1)
4724                 *newConnPtr=(*iter)+iz*deltaPerLev;
4725               else
4726                 *newConnPtr=-1;
4727             }
4728           else
4729             *newConnPtr=(*iter);
4730         }
4731     }
4732   ret->setConnectivity(newConn,newConnI,true);
4733   ret->setCoords(getCoords());
4734   return ret;
4735 }
4736
4737 /*!
4738  * Checks if \a this mesh is constituted by only quadratic cells.
4739  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4740  *  \throw If the coordinates array is not set.
4741  *  \throw If the nodal connectivity of cells is not defined.
4742  */
4743 bool MEDCouplingUMesh::isFullyQuadratic() const
4744 {
4745   checkFullyDefined();
4746   bool ret=true;
4747   int nbOfCells=getNumberOfCells();
4748   for(int i=0;i<nbOfCells && ret;i++)
4749     {
4750       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4751       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4752       ret=cm.isQuadratic();
4753     }
4754   return ret;
4755 }
4756
4757 /*!
4758  * Checks if \a this mesh includes any quadratic cell.
4759  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4760  *  \throw If the coordinates array is not set.
4761  *  \throw If the nodal connectivity of cells is not defined.
4762  */
4763 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4764 {
4765   checkFullyDefined();
4766   bool ret=false;
4767   int nbOfCells=getNumberOfCells();
4768   for(int i=0;i<nbOfCells && !ret;i++)
4769     {
4770       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4771       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4772       ret=cm.isQuadratic();
4773     }
4774   return ret;
4775 }
4776
4777 /*!
4778  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4779  * this mesh, it remains unchanged.
4780  *  \throw If the coordinates array is not set.
4781  *  \throw If the nodal connectivity of cells is not defined.
4782  */
4783 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4784 {
4785   checkFullyDefined();
4786   int nbOfCells=getNumberOfCells();
4787   int delta=0;
4788   const int *iciptr=_nodal_connec_index->getConstPointer();
4789   for(int i=0;i<nbOfCells;i++)
4790     {
4791       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4792       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4793       if(cm.isQuadratic())
4794         {
4795           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4796           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4797           if(!cml.isDynamic())
4798             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4799           else
4800             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4801         }
4802     }
4803   if(delta==0)
4804     return ;
4805   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4806   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4807   const int *icptr=_nodal_connec->getConstPointer();
4808   newConn->alloc(getMeshLength()-delta,1);
4809   newConnI->alloc(nbOfCells+1,1);
4810   int *ocptr=newConn->getPointer();
4811   int *ociptr=newConnI->getPointer();
4812   *ociptr=0;
4813   _types.clear();
4814   for(int i=0;i<nbOfCells;i++,ociptr++)
4815     {
4816       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4817       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4818       if(!cm.isQuadratic())
4819         {
4820           _types.insert(type);
4821           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4822           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4823         }
4824       else
4825         {
4826           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4827           _types.insert(typel);
4828           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4829           int newNbOfNodes=cml.getNumberOfNodes();
4830           if(cml.isDynamic())
4831             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4832           *ocptr++=(int)typel;
4833           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4834           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4835         }
4836     }
4837   setConnectivity(newConn,newConnI,false);
4838 }
4839
4840 /*!
4841  * This method converts all linear cell in \a this to quadratic one.
4842  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4843  * 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)
4844  * 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.
4845  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4846  * end of the existing coordinates.
4847  * 
4848  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4849  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4850  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4851  * 
4852  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4853  *
4854  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4855  */
4856 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4857 {
4858   DataArrayInt *conn=0,*connI=0;
4859   DataArrayDouble *coords=0;
4860   std::set<INTERP_KERNEL::NormalizedCellType> types;
4861   checkFullyDefined();
4862   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4863   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4864   int meshDim=getMeshDimension();
4865   switch(conversionType)
4866     {
4867     case 0:
4868       switch(meshDim)
4869         {
4870         case 1:
4871           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4872           connSafe=conn; connISafe=connI; coordsSafe=coords;
4873           break;
4874         case 2:
4875           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4876           connSafe=conn; connISafe=connI; coordsSafe=coords;
4877           break;
4878         case 3:
4879           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4880           connSafe=conn; connISafe=connI; coordsSafe=coords;
4881           break;
4882         default:
4883           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4884         }
4885       break;
4886     case 1:
4887       {
4888         switch(meshDim)
4889         {
4890         case 1:
4891           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4892           connSafe=conn; connISafe=connI; coordsSafe=coords;
4893           break;
4894         case 2:
4895           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4896           connSafe=conn; connISafe=connI; coordsSafe=coords;
4897           break;
4898         case 3:
4899           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4900           connSafe=conn; connISafe=connI; coordsSafe=coords;
4901           break;
4902         default:
4903           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4904         }
4905         break;
4906       }
4907     default:
4908       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4909     }
4910   setConnectivity(connSafe,connISafe,false);
4911   _types=types;
4912   setCoords(coordsSafe);
4913   return ret.retn();
4914 }
4915
4916 /*!
4917  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4918  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4919  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4920  */
4921 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4922 {
4923   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4924   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4925   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4926   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4927   int nbOfCells=getNumberOfCells();
4928   int nbOfNodes=getNumberOfNodes();
4929   const int *cPtr=_nodal_connec->getConstPointer();
4930   const int *icPtr=_nodal_connec_index->getConstPointer();
4931   int lastVal=0,offset=nbOfNodes;
4932   for(int i=0;i<nbOfCells;i++,icPtr++)
4933     {
4934       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4935       if(type==INTERP_KERNEL::NORM_SEG2)
4936         {
4937           types.insert(INTERP_KERNEL::NORM_SEG3);
4938           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4939           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4940           newConn->pushBackSilent(offset++);
4941           lastVal+=4;
4942           newConnI->pushBackSilent(lastVal);
4943           ret->pushBackSilent(i);
4944         }
4945       else
4946         {
4947           types.insert(type);
4948           lastVal+=(icPtr[1]-icPtr[0]);
4949           newConnI->pushBackSilent(lastVal);
4950           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4951         }
4952     }
4953   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4954   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4955   return ret.retn();
4956 }
4957
4958 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)
4959 {
4960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4961   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4962   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4963   //
4964   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4965   DataArrayInt *conn1D=0,*conn1DI=0;
4966   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4967   DataArrayDouble *coordsTmp=0;
4968   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4969   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4970   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4971   const int *c1DPtr=conn1D->begin();
4972   const int *c1DIPtr=conn1DI->begin();
4973   int nbOfCells=getNumberOfCells();
4974   const int *cPtr=_nodal_connec->getConstPointer();
4975   const int *icPtr=_nodal_connec_index->getConstPointer();
4976   int lastVal=0;
4977   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4978     {
4979       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4980       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4981       if(!cm.isQuadratic())
4982         {
4983           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4984           types.insert(typ2); newConn->pushBackSilent(typ2);
4985           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4986           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4987             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4988           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4989           newConnI->pushBackSilent(lastVal);
4990           ret->pushBackSilent(i);
4991         }
4992       else
4993         {
4994           types.insert(typ);
4995           lastVal+=(icPtr[1]-icPtr[0]);
4996           newConnI->pushBackSilent(lastVal);
4997           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4998         }
4999     }
5000   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5001   return ret.retn();
5002 }
5003
5004 /*!
5005  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5006  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5007  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5008  */
5009 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5010 {
5011   
5012   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5013   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5014   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5015 }
5016
5017 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5018 {
5019   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5020   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5021   //
5022   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5023   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5024   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5025   //
5026   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5027   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5028   DataArrayInt *conn1D=0,*conn1DI=0;
5029   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5030   DataArrayDouble *coordsTmp=0;
5031   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5032   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5033   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5034   const int *c1DPtr=conn1D->begin();
5035   const int *c1DIPtr=conn1DI->begin();
5036   int nbOfCells=getNumberOfCells();
5037   const int *cPtr=_nodal_connec->getConstPointer();
5038   const int *icPtr=_nodal_connec_index->getConstPointer();
5039   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5040   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5041     {
5042       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5043       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5044       if(!cm.isQuadratic())
5045         {
5046           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5047           types.insert(typ2); newConn->pushBackSilent(typ2);
5048           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5049           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5050             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5051           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5052           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5053           newConnI->pushBackSilent(lastVal);
5054           ret->pushBackSilent(i);
5055         }
5056       else
5057         {
5058           types.insert(typ);
5059           lastVal+=(icPtr[1]-icPtr[0]);
5060           newConnI->pushBackSilent(lastVal);
5061           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5062         }
5063     }
5064   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5065   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5066   return ret.retn();
5067 }
5068
5069 /*!
5070  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5071  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5072  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5073  */
5074 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5075 {
5076   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5077   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5078   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5079 }
5080
5081 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5082 {
5083   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5084   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5085   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5086   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5087   //
5088   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5089   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5090   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5091   //
5092   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5093   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5094   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5095   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5096   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5097   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5098   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5099   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5100   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5101   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5102   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5103   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5104   int nbOfCells=getNumberOfCells();
5105   const int *cPtr=_nodal_connec->getConstPointer();
5106   const int *icPtr=_nodal_connec_index->getConstPointer();
5107   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5108   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5109     {
5110       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5111       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5112       if(!cm.isQuadratic())
5113         {
5114           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5115           if(typ2==INTERP_KERNEL::NORM_ERROR)
5116             {
5117               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5118               throw INTERP_KERNEL::Exception(oss.str().c_str());
5119             }
5120           types.insert(typ2); newConn->pushBackSilent(typ2);
5121           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5122           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5123             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5124           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5125             {
5126               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5127               int tmpPos=newConn->getNumberOfTuples();
5128               newConn->pushBackSilent(nodeId2);
5129               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5130             }
5131           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5132           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5133           newConnI->pushBackSilent(lastVal);
5134           ret->pushBackSilent(i);
5135         }
5136       else
5137         {
5138           types.insert(typ);
5139           lastVal+=(icPtr[1]-icPtr[0]);
5140           newConnI->pushBackSilent(lastVal);
5141           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5142         }
5143     }
5144   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5145   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5146   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5147   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5148   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5149   int *c=newConn->getPointer();
5150   const int *cI(newConnI->begin());
5151   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5152     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5153   offset=coordsTmp2Safe->getNumberOfTuples();
5154   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5155     c[cI[(*elt)+1]-1]+=offset;
5156   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5157   return ret.retn();
5158 }
5159
5160 /*!
5161  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5162  * so that the number of cells remains the same. Quadratic faces are converted to
5163  * polygons. This method works only for 2D meshes in
5164  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5165  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5166  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5167  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5168  *         a polylinized edge constituting the input polygon.
5169  *  \throw If the coordinates array is not set.
5170  *  \throw If the nodal connectivity of cells is not defined.
5171  *  \throw If \a this->getMeshDimension() != 2.
5172  *  \throw If \a this->getSpaceDimension() != 2.
5173  */
5174 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5175 {
5176   checkFullyDefined();
5177   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5178     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5179   double epsa=fabs(eps);
5180   if(epsa<std::numeric_limits<double>::min())
5181     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 !");
5182   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5183   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5184   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5185   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5186   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5187   revDesc1=0; revDescIndx1=0;
5188   mDesc->tessellate2DCurve(eps);
5189   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5190   setCoords(mDesc->getCoords());
5191 }
5192
5193 /*!
5194  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5195  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5196  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5197  *         a sub-divided edge.
5198  *  \throw If the coordinates array is not set.
5199  *  \throw If the nodal connectivity of cells is not defined.
5200  *  \throw If \a this->getMeshDimension() != 1.
5201  *  \throw If \a this->getSpaceDimension() != 2.
5202  */
5203 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5204 {
5205   checkFullyDefined();
5206   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5207     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5208   double epsa=fabs(eps);
5209   if(epsa<std::numeric_limits<double>::min())
5210     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 !");
5211   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5212   int nbCells=getNumberOfCells();
5213   int nbNodes=getNumberOfNodes();
5214   const int *conn=_nodal_connec->getConstPointer();
5215   const int *connI=_nodal_connec_index->getConstPointer();
5216   const double *coords=_coords->getConstPointer();
5217   std::vector<double> addCoo;
5218   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5219   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5220   newConnI->alloc(nbCells+1,1);
5221   int *newConnIPtr=newConnI->getPointer();
5222   *newConnIPtr=0;
5223   int tmp1[3];
5224   INTERP_KERNEL::Node *tmp2[3];
5225   std::set<INTERP_KERNEL::NormalizedCellType> types;
5226   for(int i=0;i<nbCells;i++,newConnIPtr++)
5227     {
5228       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5229       if(cm.isQuadratic())
5230         {//assert(connI[i+1]-connI[i]-1==3)
5231           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5232           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5233           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5234           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5235           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5236           if(eac)
5237             {
5238               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5239               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5240               delete eac;
5241               newConnIPtr[1]=(int)newConn.size();
5242             }
5243           else
5244             {
5245               types.insert(INTERP_KERNEL::NORM_SEG2);
5246               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5247               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5248               newConnIPtr[1]=newConnIPtr[0]+3;
5249             }
5250         }
5251       else
5252         {
5253           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5254           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5255           newConnIPtr[1]=newConnIPtr[0]+3;
5256         }
5257     }
5258   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5259     return ;
5260   _types=types;
5261   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5262   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5263   newConnArr->alloc((int)newConn.size(),1);
5264   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5265   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5266   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5267   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5268   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5269   std::copy(addCoo.begin(),addCoo.end(),work);
5270   DataArrayDouble::SetArrayIn(newCoords,_coords);
5271   updateTime();
5272 }
5273
5274 /*!
5275  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5276  * In addition, returns an array mapping new cells to old ones. <br>
5277  * This method typically increases the number of cells in \a this mesh
5278  * but the number of nodes remains \b unchanged.
5279  * That's why the 3D splitting policies
5280  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5281  *  \param [in] policy - specifies a pattern used for splitting.
5282  * The semantic of \a policy is:
5283  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5284  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5285  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5286  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5287  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5288  *          an id of old cell producing it. The caller is to delete this array using
5289  *         decrRef() as it is no more needed. 
5290  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5291  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5292  *          and \a this->getMeshDimension() != 3. 
5293  *  \throw If \a policy is not one of the four discussed above.
5294  *  \throw If the nodal connectivity of cells is not defined.
5295  */
5296 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5297 {
5298   switch(policy)
5299     {
5300     case 0:
5301       return simplexizePol0();
5302     case 1:
5303       return simplexizePol1();
5304     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5305       return simplexizePlanarFace5();
5306     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5307       return simplexizePlanarFace6();
5308     default:
5309       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)");
5310     }
5311 }
5312
5313 /*!
5314  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5315  * - 1D: INTERP_KERNEL::NORM_SEG2
5316  * - 2D: INTERP_KERNEL::NORM_TRI3
5317  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5318  *
5319  * This method is useful for users that need to use P1 field services as
5320  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5321  * All these methods need mesh support containing only simplex cells.
5322  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5323  *  \throw If the coordinates array is not set.
5324  *  \throw If the nodal connectivity of cells is not defined.
5325  *  \throw If \a this->getMeshDimension() < 1.
5326  */
5327 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5328 {
5329   checkFullyDefined();
5330   int mdim=getMeshDimension();
5331   if(mdim<1 || mdim>3)
5332     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5333   int nbCells=getNumberOfCells();
5334   const int *conn=_nodal_connec->getConstPointer();
5335   const int *connI=_nodal_connec_index->getConstPointer();
5336   for(int i=0;i<nbCells;i++)
5337     {
5338       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5339       if(!cm.isSimplex())
5340         return false;
5341     }
5342   return true;
5343 }
5344
5345 /*!
5346  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5347  */
5348 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5349 {
5350   checkConnectivityFullyDefined();
5351   if(getMeshDimension()!=2)
5352     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5353   int nbOfCells=getNumberOfCells();
5354   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5355   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5356   ret->alloc(nbOfCells+nbOfCutCells,1);
5357   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5358   int *retPt=ret->getPointer();
5359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5361   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5362   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5363   int *pt=newConn->getPointer();
5364   int *ptI=newConnI->getPointer();
5365   ptI[0]=0;
5366   const int *oldc=_nodal_connec->getConstPointer();
5367   const int *ci=_nodal_connec_index->getConstPointer();
5368   for(int i=0;i<nbOfCells;i++,ci++)
5369     {
5370       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5371         {
5372           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5373                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5374           pt=std::copy(tmp,tmp+8,pt);
5375           ptI[1]=ptI[0]+4;
5376           ptI[2]=ptI[0]+8;
5377           *retPt++=i;
5378           *retPt++=i;
5379           ptI+=2;
5380         }
5381       else
5382         {
5383           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5384           ptI[1]=ptI[0]+ci[1]-ci[0];
5385           ptI++;
5386           *retPt++=i;
5387         }
5388     }
5389   _nodal_connec->decrRef();
5390   _nodal_connec=newConn.retn();
5391   _nodal_connec_index->decrRef();
5392   _nodal_connec_index=newConnI.retn();
5393   computeTypes();
5394   updateTime();
5395   return ret.retn();
5396 }
5397
5398 /*!
5399  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5400  */
5401 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5402 {
5403   checkConnectivityFullyDefined();
5404   if(getMeshDimension()!=2)
5405     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5406   int nbOfCells=getNumberOfCells();
5407   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5408   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5409   ret->alloc(nbOfCells+nbOfCutCells,1);
5410   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5411   int *retPt=ret->getPointer();
5412   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5413   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5414   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5415   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5416   int *pt=newConn->getPointer();
5417   int *ptI=newConnI->getPointer();
5418   ptI[0]=0;
5419   const int *oldc=_nodal_connec->getConstPointer();
5420   const int *ci=_nodal_connec_index->getConstPointer();
5421   for(int i=0;i<nbOfCells;i++,ci++)
5422     {
5423       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5424         {
5425           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5426                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5427           pt=std::copy(tmp,tmp+8,pt);
5428           ptI[1]=ptI[0]+4;
5429           ptI[2]=ptI[0]+8;
5430           *retPt++=i;
5431           *retPt++=i;
5432           ptI+=2;
5433         }
5434       else
5435         {
5436           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5437           ptI[1]=ptI[0]+ci[1]-ci[0];
5438           ptI++;
5439           *retPt++=i;
5440         }
5441     }
5442   _nodal_connec->decrRef();
5443   _nodal_connec=newConn.retn();
5444   _nodal_connec_index->decrRef();
5445   _nodal_connec_index=newConnI.retn();
5446   computeTypes();
5447   updateTime();
5448   return ret.retn();
5449 }
5450
5451 /*!
5452  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5453  */
5454 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5455 {
5456   checkConnectivityFullyDefined();
5457   if(getMeshDimension()!=3)
5458     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5459   int nbOfCells=getNumberOfCells();
5460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5461   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5462   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5463   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5464   int *retPt=ret->getPointer();
5465   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5466   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5467   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5468   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5469   int *pt=newConn->getPointer();
5470   int *ptI=newConnI->getPointer();
5471   ptI[0]=0;
5472   const int *oldc=_nodal_connec->getConstPointer();
5473   const int *ci=_nodal_connec_index->getConstPointer();
5474   for(int i=0;i<nbOfCells;i++,ci++)
5475     {
5476       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5477         {
5478           for(int j=0;j<5;j++,pt+=5,ptI++)
5479             {
5480               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5481               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];
5482               *retPt++=i;
5483               ptI[1]=ptI[0]+5;
5484             }
5485         }
5486       else
5487         {
5488           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5489           ptI[1]=ptI[0]+ci[1]-ci[0];
5490           ptI++;
5491           *retPt++=i;
5492         }
5493     }
5494   _nodal_connec->decrRef();
5495   _nodal_connec=newConn.retn();
5496   _nodal_connec_index->decrRef();
5497   _nodal_connec_index=newConnI.retn();
5498   computeTypes();
5499   updateTime();
5500   return ret.retn();
5501 }
5502
5503 /*!
5504  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5505  */
5506 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5507 {
5508   checkConnectivityFullyDefined();
5509   if(getMeshDimension()!=3)
5510     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5511   int nbOfCells=getNumberOfCells();
5512   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5513   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5514   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5515   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5516   int *retPt=ret->getPointer();
5517   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5518   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5519   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5520   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5521   int *pt=newConn->getPointer();
5522   int *ptI=newConnI->getPointer();
5523   ptI[0]=0;
5524   const int *oldc=_nodal_connec->getConstPointer();
5525   const int *ci=_nodal_connec_index->getConstPointer();
5526   for(int i=0;i<nbOfCells;i++,ci++)
5527     {
5528       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5529         {
5530           for(int j=0;j<6;j++,pt+=5,ptI++)
5531             {
5532               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5533               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];
5534               *retPt++=i;
5535               ptI[1]=ptI[0]+5;
5536             }
5537         }
5538       else
5539         {
5540           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5541           ptI[1]=ptI[0]+ci[1]-ci[0];
5542           ptI++;
5543           *retPt++=i;
5544         }
5545     }
5546   _nodal_connec->decrRef();
5547   _nodal_connec=newConn.retn();
5548   _nodal_connec_index->decrRef();
5549   _nodal_connec_index=newConnI.retn();
5550   computeTypes();
5551   updateTime();
5552   return ret.retn();
5553 }
5554
5555 /*!
5556  * 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.
5557  * This method completly ignore coordinates.
5558  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5559  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5560  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5561  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5562  */
5563 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5564 {
5565   checkFullyDefined();
5566   if(getMeshDimension()!=2)
5567     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5568   int nbOfCells=getNumberOfCells();
5569   int *connI=_nodal_connec_index->getPointer();
5570   int newConnLgth=0;
5571   for(int i=0;i<nbOfCells;i++,connI++)
5572     {
5573       int offset=descIndex[i];
5574       int nbOfEdges=descIndex[i+1]-offset;
5575       //
5576       bool ddirect=desc[offset+nbOfEdges-1]>0;
5577       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5578       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5579       for(int j=0;j<nbOfEdges;j++)
5580         {
5581           bool direct=desc[offset+j]>0;
5582           int edgeId=std::abs(desc[offset+j])-1;
5583           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5584             {
5585               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5586               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5587               int ref2=direct?id1:id2;
5588               if(ref==ref2)
5589                 {
5590                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5591                   newConnLgth+=nbOfSubNodes-1;
5592                   ref=direct?id2:id1;
5593                 }
5594               else
5595                 {
5596                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5597                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5598                 }
5599             }
5600           else
5601             {
5602               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5603             }
5604         }
5605       newConnLgth++;//+1 is for cell type
5606       connI[1]=newConnLgth;
5607     }
5608   //
5609   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5610   newConn->alloc(newConnLgth,1);
5611   int *work=newConn->getPointer();
5612   for(int i=0;i<nbOfCells;i++)
5613     {
5614       *work++=INTERP_KERNEL::NORM_POLYGON;
5615       int offset=descIndex[i];
5616       int nbOfEdges=descIndex[i+1]-offset;
5617       for(int j=0;j<nbOfEdges;j++)
5618         {
5619           bool direct=desc[offset+j]>0;
5620           int edgeId=std::abs(desc[offset+j])-1;
5621           if(direct)
5622             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5623           else
5624             {
5625               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5626               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5627               work=std::copy(it,it+nbOfSubNodes-1,work);
5628             }
5629         }
5630     }
5631   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5632   _types.clear();
5633   if(nbOfCells>0)
5634     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5635 }
5636
5637 /*!
5638  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5639  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5640  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5641  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5642  * so it can be useful to call mergeNodes() before calling this method.
5643  *  \throw If \a this->getMeshDimension() <= 1.
5644  *  \throw If the coordinates array is not set.
5645  *  \throw If the nodal connectivity of cells is not defined.
5646  */
5647 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5648 {
5649   checkFullyDefined();
5650   if(getMeshDimension()<=1)
5651     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5652   int nbOfCells=getNumberOfCells();
5653   if(nbOfCells<1)
5654     return ;
5655   int initMeshLgth=getMeshLength();
5656   int *conn=_nodal_connec->getPointer();
5657   int *index=_nodal_connec_index->getPointer();
5658   int posOfCurCell=0;
5659   int newPos=0;
5660   int lgthOfCurCell;
5661   for(int i=0;i<nbOfCells;i++)
5662     {
5663       lgthOfCurCell=index[i+1]-posOfCurCell;
5664       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5665       int newLgth;
5666       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5667                                                                                                      conn+newPos+1,newLgth);
5668       conn[newPos]=newType;
5669       newPos+=newLgth+1;
5670       posOfCurCell=index[i+1];
5671       index[i+1]=newPos;
5672     }
5673   if(newPos!=initMeshLgth)
5674     _nodal_connec->reAlloc(newPos);
5675   computeTypes();
5676 }
5677
5678 /*!
5679  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5680  * A cell is considered to be oriented correctly if an angle between its
5681  * normal vector and a given vector is less than \c PI / \c 2.
5682  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5683  *         cells. 
5684  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5685  *         checked.
5686  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5687  *         is not cleared before filling in.
5688  *  \throw If \a this->getMeshDimension() != 2.
5689  *  \throw If \a this->getSpaceDimension() != 3.
5690  *
5691  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5692  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5693  */
5694 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5695 {
5696   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5697     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5698   int nbOfCells=getNumberOfCells();
5699   const int *conn=_nodal_connec->getConstPointer();
5700   const int *connI=_nodal_connec_index->getConstPointer();
5701   const double *coordsPtr=_coords->getConstPointer();
5702   for(int i=0;i<nbOfCells;i++)
5703     {
5704       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5705       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5706         {
5707           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5708           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5709             cells.push_back(i);
5710         }
5711     }
5712 }
5713
5714 /*!
5715  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5716  * considered to be oriented correctly if an angle between its normal vector and a
5717  * given vector is less than \c PI / \c 2. 
5718  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5719  *         cells. 
5720  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5721  *         checked.
5722  *  \throw If \a this->getMeshDimension() != 2.
5723  *  \throw If \a this->getSpaceDimension() != 3.
5724  *
5725  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5726  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5727  */
5728 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5729 {
5730   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5731     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5732   int nbOfCells=getNumberOfCells();
5733   int *conn=_nodal_connec->getPointer();
5734   const int *connI=_nodal_connec_index->getConstPointer();
5735   const double *coordsPtr=_coords->getConstPointer();
5736   bool isModified=false;
5737   for(int i=0;i<nbOfCells;i++)
5738     {
5739       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5740       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5741         {
5742           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5743           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5744             {
5745               isModified=true;
5746               std::vector<int> tmp(connI[i+1]-connI[i]-2);
5747               std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5748               std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5749             }
5750         }
5751     }
5752   if(isModified)
5753     _nodal_connec->declareAsNew();
5754   updateTime();
5755 }
5756
5757 /*!
5758  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5759  * oriented facets. The normal vector of the facet should point out of the cell.
5760  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5761  *         is not cleared before filling in.
5762  *  \throw If \a this->getMeshDimension() != 3.
5763  *  \throw If \a this->getSpaceDimension() != 3.
5764  *  \throw If the coordinates array is not set.
5765  *  \throw If the nodal connectivity of cells is not defined.
5766  *
5767  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5768  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5769  */
5770 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5771 {
5772   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5773     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5774   int nbOfCells=getNumberOfCells();
5775   const int *conn=_nodal_connec->getConstPointer();
5776   const int *connI=_nodal_connec_index->getConstPointer();
5777   const double *coordsPtr=_coords->getConstPointer();
5778   for(int i=0;i<nbOfCells;i++)
5779     {
5780       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5781       if(type==INTERP_KERNEL::NORM_POLYHED)
5782         {
5783           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5784             cells.push_back(i);
5785         }
5786     }
5787 }
5788
5789 /*!
5790  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5791  * out of the cell. 
5792  *  \throw If \a this->getMeshDimension() != 3.
5793  *  \throw If \a this->getSpaceDimension() != 3.
5794  *  \throw If the coordinates array is not set.
5795  *  \throw If the nodal connectivity of cells is not defined.
5796  *  \throw If the reparation fails.
5797  *
5798  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5799  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5800  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5801  */
5802 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5803 {
5804   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5805     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5806   int nbOfCells=getNumberOfCells();
5807   int *conn=_nodal_connec->getPointer();
5808   const int *connI=_nodal_connec_index->getConstPointer();
5809   const double *coordsPtr=_coords->getConstPointer();
5810   for(int i=0;i<nbOfCells;i++)
5811     {
5812       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5813       if(type==INTERP_KERNEL::NORM_POLYHED)
5814         {
5815           try
5816             {
5817               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5818                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5819             }
5820           catch(INTERP_KERNEL::Exception& e)
5821             {
5822               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5823               throw INTERP_KERNEL::Exception(oss.str().c_str());
5824             }
5825         }
5826     }
5827   updateTime();
5828 }
5829
5830 /*!
5831  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5832  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5833  * according to which the first facet of the cell should be oriented to have the normal vector
5834  * pointing out of cell.
5835  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5836  *         cells. The caller is to delete this array using decrRef() as it is no more
5837  *         needed. 
5838  *  \throw If \a this->getMeshDimension() != 3.
5839  *  \throw If \a this->getSpaceDimension() != 3.
5840  *  \throw If the coordinates array is not set.
5841  *  \throw If the nodal connectivity of cells is not defined.
5842  *
5843  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5844  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5845  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5846  */
5847 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5848 {
5849   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5850   if(getMeshDimension()!=3)
5851     throw INTERP_KERNEL::Exception(msg);
5852   int spaceDim=getSpaceDimension();
5853   if(spaceDim!=3)
5854     throw INTERP_KERNEL::Exception(msg);
5855   //
5856   int nbOfCells=getNumberOfCells();
5857   int *conn=_nodal_connec->getPointer();
5858   const int *connI=_nodal_connec_index->getConstPointer();
5859   const double *coo=getCoords()->getConstPointer();
5860   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5861   for(int i=0;i<nbOfCells;i++)
5862     {
5863       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5864       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5865         {
5866           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5867             {
5868               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5869               cells->pushBackSilent(i);
5870             }
5871         }
5872     }
5873   return cells.retn();
5874 }
5875
5876 /*!
5877  * This method is a faster method to correct orientation of all 3D cells in \a this.
5878  * 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.
5879  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5880  * 
5881  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5882  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5883  */
5884 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5885 {
5886   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5887     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5888   int nbOfCells=getNumberOfCells();
5889   int *conn=_nodal_connec->getPointer();
5890   const int *connI=_nodal_connec_index->getConstPointer();
5891   const double *coordsPtr=_coords->getConstPointer();
5892   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5893   for(int i=0;i<nbOfCells;i++)
5894     {
5895       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5896       switch(type)
5897         {
5898         case INTERP_KERNEL::NORM_TETRA4:
5899           {
5900             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5901               {
5902                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5903                 ret->pushBackSilent(i);
5904               }
5905             break;
5906           }
5907         case INTERP_KERNEL::NORM_PYRA5:
5908           {
5909             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5910               {
5911                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5912                 ret->pushBackSilent(i);
5913               }
5914             break;
5915           }
5916         case INTERP_KERNEL::NORM_PENTA6:
5917         case INTERP_KERNEL::NORM_HEXA8:
5918         case INTERP_KERNEL::NORM_HEXGP12:
5919           {
5920             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5921               {
5922                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5923                 ret->pushBackSilent(i);
5924               }
5925             break;
5926           }
5927         case INTERP_KERNEL::NORM_POLYHED:
5928           {
5929             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5930               {
5931                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5932                 ret->pushBackSilent(i);
5933               }
5934             break;
5935           }
5936         default:
5937           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 !");
5938         }
5939     }
5940   updateTime();
5941   return ret.retn();
5942 }
5943
5944 /*!
5945  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5946  * If it is not the case an exception will be thrown.
5947  * This method is fast because the first cell of \a this is used to compute the plane.
5948  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5949  * \param pos output of size at least 3 used to store a point owned of searched plane.
5950  */
5951 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5952 {
5953   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5954     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5955   const int *conn=_nodal_connec->getConstPointer();
5956   const int *connI=_nodal_connec_index->getConstPointer();
5957   const double *coordsPtr=_coords->getConstPointer();
5958   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5959   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5960 }
5961
5962 /*!
5963  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5964  * cells. Currently cells of the following types are treated:
5965  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5966  * For a cell of other type an exception is thrown.
5967  * Space dimension of a 2D mesh can be either 2 or 3.
5968  * The Edge Ratio of a cell \f$t\f$ is: 
5969  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5970  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5971  *  the smallest edge lengths of \f$t\f$.
5972  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5973  *          cells and one time, lying on \a this mesh. The caller is to delete this
5974  *          field using decrRef() as it is no more needed. 
5975  *  \throw If the coordinates array is not set.
5976  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5977  *  \throw If the connectivity data array has more than one component.
5978  *  \throw If the connectivity data array has a named component.
5979  *  \throw If the connectivity index data array has more than one component.
5980  *  \throw If the connectivity index data array has a named component.
5981  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5982  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5983  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5984  */
5985 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5986 {
5987   checkCoherency();
5988   int spaceDim=getSpaceDimension();
5989   int meshDim=getMeshDimension();
5990   if(spaceDim!=2 && spaceDim!=3)
5991     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5992   if(meshDim!=2 && meshDim!=3)
5993     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5994   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5995   ret->setMesh(this);
5996   int nbOfCells=getNumberOfCells();
5997   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5998   arr->alloc(nbOfCells,1);
5999   double *pt=arr->getPointer();
6000   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6001   const int *conn=_nodal_connec->getConstPointer();
6002   const int *connI=_nodal_connec_index->getConstPointer();
6003   const double *coo=_coords->getConstPointer();
6004   double tmp[12];
6005   for(int i=0;i<nbOfCells;i++,pt++)
6006     {
6007       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6008       switch(t)
6009         {
6010           case INTERP_KERNEL::NORM_TRI3:
6011             {
6012               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6013               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6014               break;
6015             }
6016           case INTERP_KERNEL::NORM_QUAD4:
6017             {
6018               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6019               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6020               break;
6021             }
6022           case INTERP_KERNEL::NORM_TETRA4:
6023             {
6024               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6025               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6026               break;
6027             }
6028         default:
6029           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6030         }
6031       conn+=connI[i+1]-connI[i];
6032     }
6033   ret->setName("EdgeRatio");
6034   ret->synchronizeTimeWithSupport();
6035   return ret.retn();
6036 }
6037
6038 /*!
6039  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6040  * cells. Currently cells of the following types are treated:
6041  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6042  * For a cell of other type an exception is thrown.
6043  * Space dimension of a 2D mesh can be either 2 or 3.
6044  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6045  *          cells and one time, lying on \a this mesh. The caller is to delete this
6046  *          field using decrRef() as it is no more needed. 
6047  *  \throw If the coordinates array is not set.
6048  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6049  *  \throw If the connectivity data array has more than one component.
6050  *  \throw If the connectivity data array has a named component.
6051  *  \throw If the connectivity index data array has more than one component.
6052  *  \throw If the connectivity index data array has a named component.
6053  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6054  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6055  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6056  */
6057 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6058 {
6059   checkCoherency();
6060   int spaceDim=getSpaceDimension();
6061   int meshDim=getMeshDimension();
6062   if(spaceDim!=2 && spaceDim!=3)
6063     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6064   if(meshDim!=2 && meshDim!=3)
6065     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6066   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6067   ret->setMesh(this);
6068   int nbOfCells=getNumberOfCells();
6069   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6070   arr->alloc(nbOfCells,1);
6071   double *pt=arr->getPointer();
6072   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6073   const int *conn=_nodal_connec->getConstPointer();
6074   const int *connI=_nodal_connec_index->getConstPointer();
6075   const double *coo=_coords->getConstPointer();
6076   double tmp[12];
6077   for(int i=0;i<nbOfCells;i++,pt++)
6078     {
6079       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6080       switch(t)
6081         {
6082           case INTERP_KERNEL::NORM_TRI3:
6083             {
6084               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6085               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6086               break;
6087             }
6088           case INTERP_KERNEL::NORM_QUAD4:
6089             {
6090               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6091               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6092               break;
6093             }
6094           case INTERP_KERNEL::NORM_TETRA4:
6095             {
6096               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6097               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6098               break;
6099             }
6100         default:
6101           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6102         }
6103       conn+=connI[i+1]-connI[i];
6104     }
6105   ret->setName("AspectRatio");
6106   ret->synchronizeTimeWithSupport();
6107   return ret.retn();
6108 }
6109
6110 /*!
6111  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6112  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6113  * treated: INTERP_KERNEL::NORM_QUAD4.
6114  * For a cell of other type an exception is thrown.
6115  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6116  *          cells and one time, lying on \a this mesh. The caller is to delete this
6117  *          field using decrRef() as it is no more needed. 
6118  *  \throw If the coordinates array is not set.
6119  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6120  *  \throw If the connectivity data array has more than one component.
6121  *  \throw If the connectivity data array has a named component.
6122  *  \throw If the connectivity index data array has more than one component.
6123  *  \throw If the connectivity index data array has a named component.
6124  *  \throw If \a this->getMeshDimension() != 2.
6125  *  \throw If \a this->getSpaceDimension() != 3.
6126  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6127  */
6128 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6129 {
6130   checkCoherency();
6131   int spaceDim=getSpaceDimension();
6132   int meshDim=getMeshDimension();
6133   if(spaceDim!=3)
6134     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6135   if(meshDim!=2)
6136     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6137   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6138   ret->setMesh(this);
6139   int nbOfCells=getNumberOfCells();
6140   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6141   arr->alloc(nbOfCells,1);
6142   double *pt=arr->getPointer();
6143   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6144   const int *conn=_nodal_connec->getConstPointer();
6145   const int *connI=_nodal_connec_index->getConstPointer();
6146   const double *coo=_coords->getConstPointer();
6147   double tmp[12];
6148   for(int i=0;i<nbOfCells;i++,pt++)
6149     {
6150       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6151       switch(t)
6152         {
6153           case INTERP_KERNEL::NORM_QUAD4:
6154             {
6155               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6156               *pt=INTERP_KERNEL::quadWarp(tmp);
6157               break;
6158             }
6159         default:
6160           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6161         }
6162       conn+=connI[i+1]-connI[i];
6163     }
6164   ret->setName("Warp");
6165   ret->synchronizeTimeWithSupport();
6166   return ret.retn();
6167 }
6168
6169
6170 /*!
6171  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6172  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6173  * treated: INTERP_KERNEL::NORM_QUAD4.
6174  * For a cell of other type an exception is thrown.
6175  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6176  *          cells and one time, lying on \a this mesh. The caller is to delete this
6177  *          field using decrRef() as it is no more needed. 
6178  *  \throw If the coordinates array is not set.
6179  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6180  *  \throw If the connectivity data array has more than one component.
6181  *  \throw If the connectivity data array has a named component.
6182  *  \throw If the connectivity index data array has more than one component.
6183  *  \throw If the connectivity index data array has a named component.
6184  *  \throw If \a this->getMeshDimension() != 2.
6185  *  \throw If \a this->getSpaceDimension() != 3.
6186  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6187  */
6188 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6189 {
6190   checkCoherency();
6191   int spaceDim=getSpaceDimension();
6192   int meshDim=getMeshDimension();
6193   if(spaceDim!=3)
6194     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6195   if(meshDim!=2)
6196     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6197   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6198   ret->setMesh(this);
6199   int nbOfCells=getNumberOfCells();
6200   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6201   arr->alloc(nbOfCells,1);
6202   double *pt=arr->getPointer();
6203   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6204   const int *conn=_nodal_connec->getConstPointer();
6205   const int *connI=_nodal_connec_index->getConstPointer();
6206   const double *coo=_coords->getConstPointer();
6207   double tmp[12];
6208   for(int i=0;i<nbOfCells;i++,pt++)
6209     {
6210       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6211       switch(t)
6212         {
6213           case INTERP_KERNEL::NORM_QUAD4:
6214             {
6215               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6216               *pt=INTERP_KERNEL::quadSkew(tmp);
6217               break;
6218             }
6219         default:
6220           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6221         }
6222       conn+=connI[i+1]-connI[i];
6223     }
6224   ret->setName("Skew");
6225   ret->synchronizeTimeWithSupport();
6226   return ret.retn();
6227 }
6228
6229 /*!
6230  * This method aggregate the bbox of each cell and put it into bbox parameter.
6231  * \param bbox out parameter of size 2*spacedim*nbOfcells.
6232  */
6233 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6234 {
6235   int spaceDim=getSpaceDimension();
6236   int nbOfCells=getNumberOfCells();
6237   bbox.resize(2*nbOfCells*spaceDim);
6238   for(int i=0;i<nbOfCells*spaceDim;i++)
6239     {
6240       bbox[2*i]=std::numeric_limits<double>::max();
6241       bbox[2*i+1]=-std::numeric_limits<double>::max();
6242     }
6243   const double *coordsPtr=_coords->getConstPointer();
6244   const int *conn=_nodal_connec->getConstPointer();
6245   const int *connI=_nodal_connec_index->getConstPointer();
6246   for(int i=0;i<nbOfCells;i++)
6247     {
6248       int offset=connI[i]+1;
6249       int nbOfNodesForCell=connI[i+1]-offset;
6250       for(int j=0;j<nbOfNodesForCell;j++)
6251         {
6252           int nodeId=conn[offset+j];
6253           if(nodeId>=0)
6254             for(int k=0;k<spaceDim;k++)
6255               {
6256                 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6257                 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6258               }
6259         }
6260     }
6261 }
6262
6263 /// @cond INTERNAL
6264
6265 namespace ParaMEDMEMImpl
6266 {
6267   class ConnReader
6268   {
6269   public:
6270     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6271     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6272   private:
6273     const int *_conn;
6274     int _val;
6275   };
6276
6277   class ConnReader2
6278   {
6279   public:
6280     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6281     bool operator() (const int& pos) { return _conn[pos]==_val; }
6282   private:
6283     const int *_conn;
6284     int _val;
6285   };
6286 }
6287
6288 /// @endcond
6289
6290 /*!
6291  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6292  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6293  * \a this is composed in cell types.
6294  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6295  * For every k in [0,n] ret[3*k+2]==0 because it has no sense here. 
6296  * This parameter is kept only for compatibility with other methode listed above.
6297  */
6298 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6299 {
6300   checkConnectivityFullyDefined();
6301   const int *conn=_nodal_connec->getConstPointer();
6302   const int *connI=_nodal_connec_index->getConstPointer();
6303   const int *work=connI;
6304   int nbOfCells=getNumberOfCells();
6305   std::size_t n=getAllTypes().size();
6306   std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
6307   std::set<INTERP_KERNEL::NormalizedCellType> types;
6308   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6309     {
6310       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6311       if(types.find(typ)!=types.end())
6312         {
6313           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6314           oss << " is not contiguous !";
6315           throw INTERP_KERNEL::Exception(oss.str().c_str());
6316         }
6317       types.insert(typ);
6318       ret[3*i]=typ;
6319       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6320       ret[3*i+1]=(int)std::distance(work,work2);
6321       work=work2;
6322     }
6323   return ret;
6324 }
6325
6326 /*!
6327  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6328  * only for types cell, type node is not managed.
6329  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6330  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6331  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6332  * If 2 or more same geometric type is in \a code and exception is thrown too.
6333  *
6334  * This method firstly checks
6335  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6336  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6337  * an exception is thrown too.
6338  * 
6339  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6340  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6341  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6342  */
6343 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6344 {
6345   if(code.empty())
6346     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6347   std::size_t sz=code.size();
6348   std::size_t n=sz/3;
6349   if(sz%3!=0)
6350     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6351   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6352   int nb=0;
6353   for(std::size_t i=0;i<n;i++)
6354     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6355       {
6356         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6357         nb+=code[3*i+1];
6358         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6359           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6360       }
6361   if(types.size()!=n)
6362     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6363   if(idsPerType.empty())
6364     {
6365       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6366         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6367       if(types.size()==_types.size())
6368         return 0;
6369     }
6370   DataArrayInt *ret=DataArrayInt::New();
6371   ret->alloc(nb,1);
6372   int *retPtr=ret->getPointer();
6373   const int *connI=_nodal_connec_index->getConstPointer();
6374   const int *conn=_nodal_connec->getConstPointer();
6375   int nbOfCells=getNumberOfCells();
6376   const int *i=connI;
6377   int kk=0;
6378   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6379     {
6380       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6381       int offset=(int)std::distance(connI,i);
6382       if(code[3*kk+2]==-1)
6383         {
6384           const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6385           std::size_t pos2=std::distance(i,j);
6386           for(std::size_t k=0;k<pos2;k++)
6387             *retPtr++=(int)k+offset;
6388           i=j;
6389         }
6390       else
6391         {
6392           retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
6393                                 retPtr,std::bind2nd(std::plus<int>(),offset));
6394         }
6395     }
6396   return ret;
6397 }
6398
6399 /*!
6400  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6401  * 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.
6402  * 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.
6403  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6404  * 
6405  * \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.
6406  * \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,
6407  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6408  * \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.
6409  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6410  * \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
6411  */
6412 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6413 {
6414   if(!profile)
6415     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6416   if(profile->getNumberOfComponents()!=1)
6417     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6418   checkConnectivityFullyDefined();
6419   const int *conn=_nodal_connec->getConstPointer();
6420   const int *connI=_nodal_connec_index->getConstPointer();
6421   int nbOfCells=getNumberOfCells();
6422   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6423   std::vector<int> typeRangeVals(1);
6424   for(const int *i=connI;i!=connI+nbOfCells;)
6425     {
6426       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6427       if(std::find(types.begin(),types.end(),curType)!=types.end())
6428         {
6429           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6430         }
6431       types.push_back(curType);
6432       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6433       typeRangeVals.push_back((int)std::distance(connI,i));
6434     }
6435   //
6436   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6437   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6438   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6439   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6440   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6441   //
6442   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6443   code.resize(3*nbOfCastsFinal);
6444   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6445   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6446   for(int i=0;i<nbOfCastsFinal;i++)
6447     {
6448       int castId=castsPresent->getIJ(i,0);
6449       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6450       idsInPflPerType2.push_back(tmp3);
6451       code[3*i]=(int)types[castId];
6452       code[3*i+1]=tmp3->getNumberOfTuples();
6453       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6454       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6455         {
6456           tmp4->copyStringInfoFrom(*profile);
6457           idsPerType2.push_back(tmp4);
6458           code[3*i+2]=(int)idsPerType2.size()-1;
6459         }
6460       else
6461         {
6462           code[3*i+2]=-1;
6463         }
6464     }
6465   std::size_t sz2=idsInPflPerType2.size();
6466   idsInPflPerType.resize(sz2);
6467   for(std::size_t i=0;i<sz2;i++)
6468     {
6469       DataArrayInt *locDa=idsInPflPerType2[i];
6470       locDa->incrRef();
6471       idsInPflPerType[i]=locDa;
6472     }
6473   std::size_t sz=idsPerType2.size();
6474   idsPerType.resize(sz);
6475   for(std::size_t i=0;i<sz;i++)
6476     {
6477       DataArrayInt *locDa=idsPerType2[i];
6478       locDa->incrRef();
6479       idsPerType[i]=locDa;
6480     }
6481 }
6482
6483 /*!
6484  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6485  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6486  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6487  * 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.
6488  */
6489 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6490 {
6491   checkFullyDefined();
6492   nM1LevMesh->checkFullyDefined();
6493   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6494     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6495   if(_coords!=nM1LevMesh->getCoords())
6496     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6497   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6498   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6499   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6500   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6501   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6502   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6503   tmp->setConnectivity(tmp0,tmp1);
6504   tmp->renumberCells(ret0->getConstPointer(),false);
6505   revDesc=tmp->getNodalConnectivity();
6506   revDescIndx=tmp->getNodalConnectivityIndex();
6507   DataArrayInt *ret=0;
6508   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6509     {
6510       int tmp2;
6511       ret->getMaxValue(tmp2);
6512       ret->decrRef();
6513       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6514       throw INTERP_KERNEL::Exception(oss.str().c_str());
6515     }
6516   nM1LevMeshIds=ret;
6517   //
6518   revDesc->incrRef();
6519   revDescIndx->incrRef();
6520   ret1->incrRef();
6521   ret0->incrRef();
6522   meshnM1Old2New=ret0;
6523   return ret1;
6524 }
6525
6526 /*!
6527  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6528  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6529  * in "Old to New" mode.
6530  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6531  *          this array using decrRef() as it is no more needed.
6532  *  \throw If the nodal connectivity of cells is not defined.
6533  */
6534 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6535 {
6536   checkConnectivityFullyDefined();
6537   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6538   renumberCells(ret->getConstPointer(),false);
6539   return ret.retn();
6540 }
6541
6542 /*!
6543  * This methods checks that cells are sorted by their types.
6544  * This method makes asumption (no check) that connectivity is correctly set before calling.
6545  */
6546 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6547 {
6548   checkFullyDefined();
6549   const int *conn=_nodal_connec->getConstPointer();
6550   const int *connI=_nodal_connec_index->getConstPointer();
6551   int nbOfCells=getNumberOfCells();
6552   std::set<INTERP_KERNEL::NormalizedCellType> types;
6553   for(const int *i=connI;i!=connI+nbOfCells;)
6554     {
6555       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6556       if(types.find(curType)!=types.end())
6557         return false;
6558       types.insert(curType);
6559       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6560     }
6561   return true;
6562 }
6563
6564 /*!
6565  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6566  * The geometric type order is specified by MED file.
6567  * 
6568  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6569  */
6570 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6571 {
6572   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6573 }
6574
6575 /*!
6576  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6577  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6578  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6579  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6580  */
6581 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6582 {
6583   checkFullyDefined();
6584   const int *conn=_nodal_connec->getConstPointer();
6585   const int *connI=_nodal_connec_index->getConstPointer();
6586   int nbOfCells=getNumberOfCells();
6587   if(nbOfCells==0)
6588     return true;
6589   int lastPos=-1;
6590   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6591   for(const int *i=connI;i!=connI+nbOfCells;)
6592     {
6593       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6594       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6595       if(isTypeExists!=orderEnd)
6596         {
6597           int pos=(int)std::distance(orderBg,isTypeExists);
6598           if(pos<=lastPos)
6599             return false;
6600           lastPos=pos;
6601           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6602         }
6603       else
6604         {
6605           if(sg.find(curType)==sg.end())
6606             {
6607               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6608               sg.insert(curType);
6609             }
6610           else
6611             return false;
6612         }
6613     }
6614   return true;
6615 }
6616
6617 /*!
6618  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6619  * 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
6620  * 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'.
6621  */
6622 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6623 {
6624   checkConnectivityFullyDefined();
6625   int nbOfCells=getNumberOfCells();
6626   const int *conn=_nodal_connec->getConstPointer();
6627   const int *connI=_nodal_connec_index->getConstPointer();
6628   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6629   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6630   tmpa->alloc(nbOfCells,1);
6631   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6632   tmpb->fillWithZero();
6633   int *tmp=tmpa->getPointer();
6634   int *tmp2=tmpb->getPointer();
6635   for(const int *i=connI;i!=connI+nbOfCells;i++)
6636     {
6637       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6638       if(where!=orderEnd)
6639         {
6640           int pos=(int)std::distance(orderBg,where);
6641           tmp2[pos]++;
6642           tmp[std::distance(connI,i)]=pos;
6643         }
6644       else
6645         {
6646           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6647           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6648           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6649           throw INTERP_KERNEL::Exception(oss.str().c_str());
6650         }
6651     }
6652   nbPerType=tmpb.retn();
6653   return tmpa.retn();
6654 }
6655
6656 /*!
6657  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6658  *
6659  * \return a new object containing the old to new correspondance.
6660  *
6661  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6662  */
6663 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6664 {
6665   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6666 }
6667
6668 /*!
6669  * 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.
6670  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6671  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6672  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6673  */
6674 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6675 {
6676   DataArrayInt *nbPerType=0;
6677   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6678   nbPerType->decrRef();
6679   return tmpa->buildPermArrPerLevel();
6680 }
6681
6682 /*!
6683  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6684  * The number of cells remains unchanged after the call of this method.
6685  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6686  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6687  *
6688  * \return the array giving the correspondance old to new.
6689  */
6690 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6691 {
6692   checkFullyDefined();
6693   computeTypes();
6694   const int *conn=_nodal_connec->getConstPointer();
6695   const int *connI=_nodal_connec_index->getConstPointer();
6696   int nbOfCells=getNumberOfCells();
6697   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6698   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6699     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6700       {
6701         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6702         types.push_back(curType);
6703         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6704       }
6705   DataArrayInt *ret=DataArrayInt::New();
6706   ret->alloc(nbOfCells,1);
6707   int *retPtr=ret->getPointer();
6708   std::fill(retPtr,retPtr+nbOfCells,-1);
6709   int newCellId=0;
6710   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6711     {
6712       for(const int *i=connI;i!=connI+nbOfCells;i++)
6713         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6714           retPtr[std::distance(connI,i)]=newCellId++;
6715     }
6716   renumberCells(retPtr,false);
6717   return ret;
6718 }
6719
6720 /*!
6721  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6722  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6723  * This method makes asumption that connectivity is correctly set before calling.
6724  */
6725 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6726 {
6727   checkFullyDefined();
6728   const int *conn=_nodal_connec->getConstPointer();
6729   const int *connI=_nodal_connec_index->getConstPointer();
6730   int nbOfCells=getNumberOfCells();
6731   std::vector<MEDCouplingUMesh *> ret;
6732   for(const int *i=connI;i!=connI+nbOfCells;)
6733     {
6734       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6735       int beginCellId=(int)std::distance(connI,i);
6736       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6737       int endCellId=(int)std::distance(connI,i);
6738       int sz=endCellId-beginCellId;
6739       int *cells=new int[sz];
6740       for(int j=0;j<sz;j++)
6741         cells[j]=beginCellId+j;
6742       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6743       delete [] cells;
6744       ret.push_back(m);
6745     }
6746   return ret;
6747 }
6748
6749 /*!
6750  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6751  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6752  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6753  *
6754  * \return a newly allocated instance, that the caller must manage.
6755  * \throw If \a this contains more than one geometric type.
6756  * \throw If the nodal connectivity of \a this is not fully defined.
6757  * \throw If the internal data is not coherent.
6758  */
6759 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6760 {
6761   checkConnectivityFullyDefined();
6762     if(_types.size()!=1)
6763     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6764   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6765   int typi=(int)typ;
6766   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6767   ret->setCoords(ret->getCoords());
6768   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6769   if(retC)
6770     {
6771       int nbCells=getNumberOfCells();
6772       int nbNodesPerCell=retC->getNumberOfNodesPerCell();
6773       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6774       int *outPtr=connOut->getPointer();
6775       const int *conn=_nodal_connec->begin();
6776       const int *connI=_nodal_connec_index->begin();
6777       nbNodesPerCell++;
6778       for(int i=0;i<nbCells;i++,connI++)
6779         {
6780           if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6781             outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6782           else
6783             {
6784               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 << ") !";
6785               throw INTERP_KERNEL::Exception(oss.str().c_str());
6786             }
6787         }
6788       retC->setNodalConnectivity(connOut);
6789     }
6790   else
6791     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : not implemented yet for non static geometric type !");
6792   return ret.retn();
6793 }
6794
6795 /*!
6796  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6797  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6798  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6799  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6800  * are not used here to avoid the build of big permutation array.
6801  *
6802  * \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
6803  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6804  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6805  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6806  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6807  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6808  * \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
6809  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6810  */
6811 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6812                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6813                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6814 {
6815   std::vector<const MEDCouplingUMesh *> ms2;
6816   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6817     if(*it)
6818       {
6819         (*it)->checkConnectivityFullyDefined();
6820         ms2.push_back(*it);
6821       }
6822   if(ms2.empty())
6823     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6824   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6825   int meshDim=ms2[0]->getMeshDimension();
6826   std::vector<const MEDCouplingUMesh *> m1ssm;
6827   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6828   //
6829   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6830   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6831   int fake=0,rk=0;
6832   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6833   ret1->alloc(0,1); ret2->alloc(0,1);
6834   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6835     {
6836       if(meshDim!=(*it)->getMeshDimension())
6837         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6838       if(refCoo!=(*it)->getCoords())
6839         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6840       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6841       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6842       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6843       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6844         {
6845           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6846           m1ssmSingleAuto.push_back(singleCell);
6847           m1ssmSingle.push_back(singleCell);
6848           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6849         }
6850     }
6851   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6852   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6853   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6854   for(std::size_t i=0;i<m1ssm.size();i++)
6855     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6856   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6857   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6858   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6859   return ret0.retn();
6860 }
6861
6862 /*!
6863  * This method returns a newly created DataArrayInt instance.
6864  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6865  */
6866 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6867 {
6868   checkFullyDefined();
6869   const int *conn=_nodal_connec->getConstPointer();
6870   const int *connIndex=_nodal_connec_index->getConstPointer();
6871   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6872   for(const int *w=begin;w!=end;w++)
6873     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6874       ret->pushBackSilent(*w);
6875   return ret.retn();
6876 }
6877
6878 /*!
6879  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6880  * are in [0:getNumberOfCells())
6881  */
6882 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6883 {
6884   checkFullyDefined();
6885   const int *conn=_nodal_connec->getConstPointer();
6886   const int *connI=_nodal_connec_index->getConstPointer();
6887   int nbOfCells=getNumberOfCells();
6888   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6889   int *tmp=new int[nbOfCells];
6890   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6891     {
6892       int j=0;
6893       for(const int *i=connI;i!=connI+nbOfCells;i++)
6894         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6895           tmp[std::distance(connI,i)]=j++;
6896     }
6897   DataArrayInt *ret=DataArrayInt::New();
6898   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6899   ret->copyStringInfoFrom(*da);
6900   int *retPtr=ret->getPointer();
6901   const int *daPtr=da->getConstPointer();
6902   int nbOfElems=da->getNbOfElems();
6903   for(int k=0;k<nbOfElems;k++)
6904     retPtr[k]=tmp[daPtr[k]];
6905   delete [] tmp;
6906   return ret;
6907 }
6908
6909 /*!
6910  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6911  * This method \b works \b for mesh sorted by type.
6912  * cells whose ids is in 'idsPerGeoType' array.
6913  * This method conserves coords and name of mesh.
6914  */
6915 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6916 {
6917   std::vector<int> code=getDistributionOfTypes();
6918   std::size_t nOfTypesInThis=code.size()/3;
6919   int sz=0,szOfType=0;
6920   for(std::size_t i=0;i<nOfTypesInThis;i++)
6921     {
6922       if(code[3*i]!=type)
6923         sz+=code[3*i+1];
6924       else
6925         szOfType=code[3*i+1];
6926     }
6927   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6928     if(*work<0 || *work>=szOfType)
6929       {
6930         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6931         oss << ". It should be in [0," << szOfType << ") !";
6932         throw INTERP_KERNEL::Exception(oss.str().c_str());
6933       }
6934   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6935   int *idsPtr=idsTokeep->getPointer();
6936   int offset=0;
6937   for(std::size_t i=0;i<nOfTypesInThis;i++)
6938     {
6939       if(code[3*i]!=type)
6940         for(int j=0;j<code[3*i+1];j++)
6941           *idsPtr++=offset+j;
6942       else
6943         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6944       offset+=code[3*i+1];
6945     }
6946   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6947   ret->copyTinyInfoFrom(this);
6948   return ret.retn();
6949 }
6950
6951 /*!
6952  * This method returns a vector of size 'this->getNumberOfCells()'.
6953  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6954  */
6955 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6956 {
6957   int ncell=getNumberOfCells();
6958   std::vector<bool> ret(ncell);
6959   const int *cI=getNodalConnectivityIndex()->getConstPointer();
6960   const int *c=getNodalConnectivity()->getConstPointer();
6961   for(int i=0;i<ncell;i++)
6962     {
6963       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6964       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6965       ret[i]=cm.isQuadratic();
6966     }
6967   return ret;
6968 }
6969
6970 /*!
6971  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6972  */
6973 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6974 {
6975   if(other->getType()!=UNSTRUCTURED)
6976     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6977   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6978   return MergeUMeshes(this,otherC);
6979 }
6980
6981 /*!
6982  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6983  * computed by averaging coordinates of cell nodes, so this method is not a right
6984  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6985  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6986  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6987  *          components. The caller is to delete this array using decrRef() as it is
6988  *          no more needed.
6989  *  \throw If the coordinates array is not set.
6990  *  \throw If the nodal connectivity of cells is not defined.
6991  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6992  */
6993 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6994 {
6995   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6996   int spaceDim=getSpaceDimension();
6997   int nbOfCells=getNumberOfCells();
6998   ret->alloc(nbOfCells,spaceDim);
6999   ret->copyStringInfoFrom(*getCoords());
7000   double *ptToFill=ret->getPointer();
7001   const int *nodal=_nodal_connec->getConstPointer();
7002   const int *nodalI=_nodal_connec_index->getConstPointer();
7003   const double *coor=_coords->getConstPointer();
7004   for(int i=0;i<nbOfCells;i++)
7005     {
7006       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7007       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7008       ptToFill+=spaceDim;
7009     }
7010   return ret.retn();
7011 }
7012
7013 /*!
7014  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7015  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7016  * 
7017  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7018  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7019  * 
7020  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7021  * \throw If \a this is not fully defined (coordinates and connectivity)
7022  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7023  */
7024 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7025 {
7026   checkFullyDefined();
7027   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7028   int spaceDim=getSpaceDimension();
7029   int nbOfCells=getNumberOfCells();
7030   int nbOfNodes=getNumberOfNodes();
7031   ret->alloc(nbOfCells,spaceDim);
7032   double *ptToFill=ret->getPointer();
7033   const int *nodal=_nodal_connec->getConstPointer();
7034   const int *nodalI=_nodal_connec_index->getConstPointer();
7035   const double *coor=_coords->getConstPointer();
7036   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7037     {
7038       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7039       std::fill(ptToFill,ptToFill+spaceDim,0.);
7040       if(type!=INTERP_KERNEL::NORM_POLYHED)
7041         {
7042           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7043             {
7044               if(*conn>=0 && *conn<nbOfNodes)
7045                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7046               else
7047                 {
7048                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7049                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7050                 }
7051             }
7052           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7053           if(nbOfNodesInCell>0)
7054             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7055           else
7056             {
7057               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7058               throw INTERP_KERNEL::Exception(oss.str().c_str());
7059             }
7060         }
7061       else
7062         {
7063           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7064           s.erase(-1);
7065           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7066             {
7067               if(*it>=0 && *it<nbOfNodes)
7068                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7069               else
7070                 {
7071                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7072                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7073                 }
7074             }
7075           if(!s.empty())
7076             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7077           else
7078             {
7079               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7080               throw INTERP_KERNEL::Exception(oss.str().c_str());
7081             }
7082         }
7083     }
7084   return ret.retn();
7085 }
7086
7087 /*!
7088  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7089  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7090  * are specified via an array of cell ids. 
7091  *  \warning Validity of the specified cell ids is not checked! 
7092  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7093  *  \param [in] begin - an array of cell ids of interest.
7094  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7095  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7096  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7097  *          caller is to delete this array using decrRef() as it is no more needed. 
7098  *  \throw If the coordinates array is not set.
7099  *  \throw If the nodal connectivity of cells is not defined.
7100  *
7101  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7102  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7103  */
7104 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7105 {
7106   DataArrayDouble *ret=DataArrayDouble::New();
7107   int spaceDim=getSpaceDimension();
7108   int nbOfTuple=(int)std::distance(begin,end);
7109   ret->alloc(nbOfTuple,spaceDim);
7110   double *ptToFill=ret->getPointer();
7111   double *tmp=new double[spaceDim];
7112   const int *nodal=_nodal_connec->getConstPointer();
7113   const int *nodalI=_nodal_connec_index->getConstPointer();
7114   const double *coor=_coords->getConstPointer();
7115   for(const int *w=begin;w!=end;w++)
7116     {
7117       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7118       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7119       ptToFill+=spaceDim;
7120     }
7121   delete [] tmp;
7122   return ret;
7123 }
7124
7125 /*!
7126  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7127  * 
7128  */
7129 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7130 {
7131   if(!da)
7132     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7133   da->checkAllocated();
7134   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7135   ret->setCoords(da);
7136   int nbOfTuples=da->getNumberOfTuples();
7137   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7138   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7139   c->alloc(2*nbOfTuples,1);
7140   cI->alloc(nbOfTuples+1,1);
7141   int *cp=c->getPointer();
7142   int *cip=cI->getPointer();
7143   *cip++=0;
7144   for(int i=0;i<nbOfTuples;i++)
7145     {
7146       *cp++=INTERP_KERNEL::NORM_POINT1;
7147       *cp++=i;
7148       *cip++=2*(i+1);
7149     }
7150   ret->setConnectivity(c,cI,true);
7151   return ret.retn();
7152 }
7153 /*!
7154  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7155  * Cells and nodes of
7156  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7157  *  \param [in] mesh1 - the first mesh.
7158  *  \param [in] mesh2 - the second mesh.
7159  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7160  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7161  *          is no more needed.
7162  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7163  *  \throw If the coordinates array is not set in none of the meshes.
7164  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7165  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7166  */
7167 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7168 {
7169   std::vector<const MEDCouplingUMesh *> tmp(2);
7170   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7171   return MergeUMeshes(tmp);
7172 }
7173
7174 /*!
7175  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7176  * Cells and nodes of
7177  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7178  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7179  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7180  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7181  *          is no more needed.
7182  *  \throw If \a a.size() == 0.
7183  *  \throw If \a a[ *i* ] == NULL.
7184  *  \throw If the coordinates array is not set in none of the meshes.
7185  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7186  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7187 */
7188 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7189 {
7190   std::size_t sz=a.size();
7191   if(sz==0)
7192     return MergeUMeshesLL(a);
7193   for(std::size_t ii=0;ii<sz;ii++)
7194     if(!a[ii])
7195       {
7196         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7197         throw INTERP_KERNEL::Exception(oss.str().c_str());
7198       }
7199   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7200   std::vector< const MEDCouplingUMesh * > aa(sz);
7201   int spaceDim=-3;
7202   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7203     {
7204       const MEDCouplingUMesh *cur=a[i];
7205       const DataArrayDouble *coo=cur->getCoords();
7206       if(coo)
7207         spaceDim=coo->getNumberOfComponents();
7208     }
7209   if(spaceDim==-3)
7210     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7211   for(std::size_t i=0;i<sz;i++)
7212     {
7213       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7214       aa[i]=bb[i];
7215     }
7216   return MergeUMeshesLL(aa);
7217 }
7218
7219 /// @cond INTERNAL
7220
7221 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7222 {
7223   if(a.empty())
7224     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7225   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7226   int meshDim=(*it)->getMeshDimension();
7227   int nbOfCells=(*it)->getNumberOfCells();
7228   int meshLgth=(*it++)->getMeshLength();
7229   for(;it!=a.end();it++)
7230     {
7231       if(meshDim!=(*it)->getMeshDimension())
7232         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7233       nbOfCells+=(*it)->getNumberOfCells();
7234       meshLgth+=(*it)->getMeshLength();
7235     }
7236   std::vector<const MEDCouplingPointSet *> aps(a.size());
7237   std::copy(a.begin(),a.end(),aps.begin());
7238   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7239   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7240   ret->setCoords(pts);
7241   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7242   c->alloc(meshLgth,1);
7243   int *cPtr=c->getPointer();
7244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7245   cI->alloc(nbOfCells+1,1);
7246   int *cIPtr=cI->getPointer();
7247   *cIPtr++=0;
7248   int offset=0;
7249   int offset2=0;
7250   for(it=a.begin();it!=a.end();it++)
7251     {
7252       int curNbOfCell=(*it)->getNumberOfCells();
7253       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7254       const int *curC=(*it)->_nodal_connec->getConstPointer();
7255       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7256       for(int j=0;j<curNbOfCell;j++)
7257         {
7258           const int *src=curC+curCI[j];
7259           *cPtr++=*src++;
7260           for(;src!=curC+curCI[j+1];src++,cPtr++)
7261             {
7262               if(*src!=-1)
7263                 *cPtr=*src+offset2;
7264               else
7265                 *cPtr=-1;
7266             }
7267         }
7268       offset+=curCI[curNbOfCell];
7269       offset2+=(*it)->getNumberOfNodes();
7270     }
7271   //
7272   ret->setConnectivity(c,cI,true);
7273   return ret.retn();
7274 }
7275
7276 /// @endcond
7277
7278 /*!
7279  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7280  * dimension and sharing the node coordinates array.
7281  * All cells of the first mesh precede all cells of the second mesh
7282  * within the result mesh. 
7283  *  \param [in] mesh1 - the first mesh.
7284  *  \param [in] mesh2 - the second mesh.
7285  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7286  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7287  *          is no more needed.
7288  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7289  *  \throw If the meshes do not share the node coordinates array.
7290  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7291  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7292  */
7293 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7294 {
7295   std::vector<const MEDCouplingUMesh *> tmp(2);
7296   tmp[0]=mesh1; tmp[1]=mesh2;
7297   return MergeUMeshesOnSameCoords(tmp);
7298 }
7299
7300 /*!
7301  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7302  * dimension and sharing the node coordinates array.
7303  * All cells of the *i*-th mesh precede all cells of the
7304  * (*i*+1)-th mesh within the result mesh.
7305  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7306  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7307  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7308  *          is no more needed.
7309  *  \throw If \a a.size() == 0.
7310  *  \throw If \a a[ *i* ] == NULL.
7311  *  \throw If the meshes do not share the node coordinates array.
7312  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7313  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7314  */
7315 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7316 {
7317   if(meshes.empty())
7318     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7319   for(std::size_t ii=0;ii<meshes.size();ii++)
7320     if(!meshes[ii])
7321       {
7322         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7323         throw INTERP_KERNEL::Exception(oss.str().c_str());
7324       }
7325   const DataArrayDouble *coords=meshes.front()->getCoords();
7326   int meshDim=meshes.front()->getMeshDimension();
7327   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7328   int meshLgth=0;
7329   int meshIndexLgth=0;
7330   for(;iter!=meshes.end();iter++)
7331     {
7332       if(coords!=(*iter)->getCoords())
7333         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7334       if(meshDim!=(*iter)->getMeshDimension())
7335         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7336       meshLgth+=(*iter)->getMeshLength();
7337       meshIndexLgth+=(*iter)->getNumberOfCells();
7338     }
7339   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7340   nodal->alloc(meshLgth,1);
7341   int *nodalPtr=nodal->getPointer();
7342   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7343   nodalIndex->alloc(meshIndexLgth+1,1);
7344   int *nodalIndexPtr=nodalIndex->getPointer();
7345   int offset=0;
7346   for(iter=meshes.begin();iter!=meshes.end();iter++)
7347     {
7348       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7349       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7350       int nbOfCells=(*iter)->getNumberOfCells();
7351       int meshLgth2=(*iter)->getMeshLength();
7352       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7353       if(iter!=meshes.begin())
7354         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7355       else
7356         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7357       offset+=meshLgth2;
7358     }
7359   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7360   ret->setName("merge");
7361   ret->setMeshDimension(meshDim);
7362   ret->setConnectivity(nodal,nodalIndex,true);
7363   ret->setCoords(coords);
7364   return ret;
7365 }
7366
7367 /*!
7368  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7369  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7370  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7371  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7372  * New" mode are returned for each input mesh.
7373  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7374  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7375  *          valid values [0,1,2], see zipConnectivityTraducer().
7376  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7377  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7378  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7379  *          no more needed.
7380  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7381  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7382  *          is no more needed.
7383  *  \throw If \a meshes.size() == 0.
7384  *  \throw If \a meshes[ *i* ] == NULL.
7385  *  \throw If the meshes do not share the node coordinates array.
7386  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7387  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7388  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7389  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7390  */
7391 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7392 {
7393   //All checks are delegated to MergeUMeshesOnSameCoords
7394   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7395   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7396   corr.resize(meshes.size());
7397   std::size_t nbOfMeshes=meshes.size();
7398   int offset=0;
7399   const int *o2nPtr=o2n->getConstPointer();
7400   for(std::size_t i=0;i<nbOfMeshes;i++)
7401     {
7402       DataArrayInt *tmp=DataArrayInt::New();
7403       int curNbOfCells=meshes[i]->getNumberOfCells();
7404       tmp->alloc(curNbOfCells,1);
7405       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7406       offset+=curNbOfCells;
7407       tmp->setName(meshes[i]->getName());
7408       corr[i]=tmp;
7409     }
7410   return ret.retn();
7411 }
7412
7413 /*!
7414  * Makes all given meshes share the nodal connectivity array. The common connectivity
7415  * array is created by concatenating the connectivity arrays of all given meshes. All
7416  * the given meshes must be of the same space dimension but dimension of cells **can
7417  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7418  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7419  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7420  *  \param [in,out] meshes - a vector of meshes to update.
7421  *  \throw If any of \a meshes is NULL.
7422  *  \throw If the coordinates array is not set in any of \a meshes.
7423  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7424  *  \throw If \a meshes are of different space dimension.
7425  */
7426 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7427 {
7428   std::size_t sz=meshes.size();
7429   if(sz==0 || sz==1)
7430     return;
7431   std::vector< const DataArrayDouble * > coords(meshes.size());
7432   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7433   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7434     {
7435       if((*it))
7436         {
7437           (*it)->checkConnectivityFullyDefined();
7438           const DataArrayDouble *coo=(*it)->getCoords();
7439           if(coo)
7440             *it2=coo;
7441           else
7442             {
7443               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7444               oss << " has no coordinate array defined !";
7445               throw INTERP_KERNEL::Exception(oss.str().c_str());
7446             }
7447         }
7448       else
7449         {
7450           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7451           oss << " is null !";
7452           throw INTERP_KERNEL::Exception(oss.str().c_str());
7453         }
7454     }
7455   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7456   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7457   int offset=(*it)->getNumberOfNodes();
7458   (*it++)->setCoords(res);
7459   for(;it!=meshes.end();it++)
7460     {
7461       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7462       (*it)->setCoords(res);
7463       (*it)->shiftNodeNumbersInConn(offset);
7464       offset+=oldNumberOfNodes;
7465     }
7466 }
7467
7468 /*!
7469  * Merges nodes coincident with a given precision within all given meshes that share
7470  * the nodal connectivity array. The given meshes **can be of different** mesh
7471  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7472  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7473  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7474  *  \param [in,out] meshes - a vector of meshes to update.
7475  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7476  *  \throw If any of \a meshes is NULL.
7477  *  \throw If the \a meshes do not share the same node coordinates array.
7478  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7479  */
7480 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7481 {
7482   if(meshes.empty())
7483     return ;
7484   std::set<const DataArrayDouble *> s;
7485   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7486     {
7487       if(*it)
7488         s.insert((*it)->getCoords());
7489       else
7490         {
7491           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 !";
7492           throw INTERP_KERNEL::Exception(oss.str().c_str());
7493         }
7494     }
7495   if(s.size()!=1)
7496     {
7497       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 !";
7498       throw INTERP_KERNEL::Exception(oss.str().c_str());
7499     }
7500   const DataArrayDouble *coo=*(s.begin());
7501   if(!coo)
7502     return;
7503   //
7504   DataArrayInt *comm,*commI;
7505   coo->findCommonTuples(eps,-1,comm,commI);
7506   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7507   int oldNbOfNodes=coo->getNumberOfTuples();
7508   int newNbOfNodes;
7509   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7510   if(oldNbOfNodes==newNbOfNodes)
7511     return ;
7512   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7513   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7514     {
7515       (*it)->renumberNodesInConn(o2n->getConstPointer());
7516       (*it)->setCoords(newCoords);
7517     } 
7518 }
7519
7520 /*!
7521  * 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.
7522  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7523  * \param isQuad specifies the policy of connectivity.
7524  * @ret in/out parameter in which the result will be append
7525  */
7526 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7527 {
7528   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7529   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7530   ret.push_back(cm.getExtrudedType());
7531   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7532   switch(flatType)
7533     {
7534     case INTERP_KERNEL::NORM_POINT1:
7535       {
7536         ret.push_back(connBg[1]);
7537         ret.push_back(connBg[1]+nbOfNodesPerLev);
7538         break;
7539       }
7540     case INTERP_KERNEL::NORM_SEG2:
7541       {
7542         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7543         ret.insert(ret.end(),conn,conn+4);
7544         break;
7545       }
7546     case INTERP_KERNEL::NORM_SEG3:
7547       {
7548         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7549         ret.insert(ret.end(),conn,conn+8);
7550         break;
7551       }
7552     case INTERP_KERNEL::NORM_QUAD4:
7553       {
7554         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7555         ret.insert(ret.end(),conn,conn+8);
7556         break;
7557       }
7558     case INTERP_KERNEL::NORM_TRI3:
7559       {
7560         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7561         ret.insert(ret.end(),conn,conn+6);
7562         break;
7563       }
7564     case INTERP_KERNEL::NORM_TRI6:
7565       {
7566         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,
7567                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7568         ret.insert(ret.end(),conn,conn+15);
7569         break;
7570       }
7571     case INTERP_KERNEL::NORM_QUAD8:
7572       {
7573         int conn[20]={
7574           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7575           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7576           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7577         };
7578         ret.insert(ret.end(),conn,conn+20);
7579         break;
7580       }
7581     case INTERP_KERNEL::NORM_POLYGON:
7582       {
7583         std::back_insert_iterator< std::vector<int> > ii(ret);
7584         std::copy(connBg+1,connEnd,ii);
7585         *ii++=-1;
7586         std::reverse_iterator<const int *> rConnBg(connEnd);
7587         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7588         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7589         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7590         for(std::size_t i=0;i<nbOfRadFaces;i++)
7591           {
7592             *ii++=-1;
7593             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7594             std::copy(conn,conn+4,ii);
7595           }
7596         break;
7597       }
7598     default:
7599       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7600     }
7601 }
7602
7603 /*!
7604  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7605  */
7606 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7607 {
7608   double v[3]={0.,0.,0.};
7609   std::size_t sz=std::distance(begin,end);
7610   if(isQuadratic)
7611     sz/=2;
7612   for(std::size_t i=0;i<sz;i++)
7613     {
7614       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];
7615       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7616       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7617     }
7618   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7619 }
7620
7621 /*!
7622  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7623  */
7624 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7625 {
7626   std::vector<std::pair<int,int> > edges;
7627   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7628   const int *bgFace=begin;
7629   for(std::size_t i=0;i<nbOfFaces;i++)
7630     {
7631       const int *endFace=std::find(bgFace+1,end,-1);
7632       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7633       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7634         {
7635           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7636           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7637             return false;
7638           edges.push_back(p1);
7639         }
7640       bgFace=endFace+1;
7641     }
7642   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7643 }
7644
7645 /*!
7646  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7647  */
7648 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7649 {
7650   double vec0[3],vec1[3];
7651   std::size_t sz=std::distance(begin,end);
7652   if(sz%2!=0)
7653     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7654   int nbOfNodes=(int)sz/2;
7655   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7656   const double *pt0=coords+3*begin[0];
7657   const double *pt1=coords+3*begin[nbOfNodes];
7658   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7659   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7660 }
7661
7662 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7663 {
7664   std::size_t sz=std::distance(begin,end);
7665   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7666   std::size_t nbOfNodes(sz/2);
7667   std::copy(begin,end,(int *)tmp);
7668   for(std::size_t j=1;j<nbOfNodes;j++)
7669     {
7670       begin[j]=tmp[nbOfNodes-j];
7671       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7672     }
7673 }
7674
7675 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7676 {
7677   std::size_t sz=std::distance(begin,end);
7678   if(sz!=4)
7679     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7680   double vec0[3],vec1[3];
7681   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7682   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]; 
7683   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;
7684 }
7685
7686 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7687 {
7688   std::size_t sz=std::distance(begin,end);
7689   if(sz!=5)
7690     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7691   double vec0[3];
7692   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7693   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7694   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7695 }
7696
7697 /*!
7698  * 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 ) 
7699  * 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
7700  * a 2D space.
7701  *
7702  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7703  * \param [in] coords the coordinates with nb of components exactly equal to 3
7704  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7705  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7706  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7707  */
7708 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7709 {
7710   int nbFaces=std::count(begin+1,end,-1)+1;
7711   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7712   double *vPtr=v->getPointer();
7713   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7714   double *pPtr=p->getPointer();
7715   const int *stFaceConn=begin+1;
7716   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7717     {
7718       const int *endFaceConn=std::find(stFaceConn,end,-1);
7719       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7720       stFaceConn=endFaceConn+1;
7721     }
7722   pPtr=p->getPointer(); vPtr=v->getPointer();
7723   DataArrayInt *comm1=0,*commI1=0;
7724   v->findCommonTuples(eps,-1,comm1,commI1);
7725   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7726   const int *comm1Ptr=comm1->getConstPointer();
7727   const int *commI1Ptr=commI1->getConstPointer();
7728   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7729   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7730   //
7731   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7732   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7733   mm->finishInsertingCells();
7734   //
7735   for(int i=0;i<nbOfGrps1;i++)
7736     {
7737       int vecId=comm1Ptr[commI1Ptr[i]];
7738       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7739       DataArrayInt *comm2=0,*commI2=0;
7740       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7741       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7742       const int *comm2Ptr=comm2->getConstPointer();
7743       const int *commI2Ptr=commI2->getConstPointer();
7744       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7745       for(int j=0;j<nbOfGrps2;j++)
7746         {
7747           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7748             {
7749               res->insertAtTheEnd(begin,end);
7750               res->pushBackSilent(-1);
7751             }
7752           else
7753             {
7754               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7755               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7756               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7757               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7758               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7759               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7760               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7761               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7762               const int *idsNodePtr=idsNode->getConstPointer();
7763               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];
7764               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7765               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7766               if(std::abs(norm)>eps)
7767                 {
7768                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7769                   mm3->rotate(center,vec,angle);
7770                 }
7771               mm3->changeSpaceDimension(2);
7772               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7773               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7774               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7775               int nbOfCells=mm4->getNumberOfCells();
7776               for(int k=0;k<nbOfCells;k++)
7777                 {
7778                   int l=0;
7779                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7780                     res->pushBackSilent(idsNodePtr[*work]);
7781                   res->pushBackSilent(-1);
7782                 }
7783             }
7784         }
7785     }
7786   res->popBackSilent();
7787 }
7788
7789 /*!
7790  * 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
7791  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7792  * 
7793  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7794  * \param [in] coords coordinates expected to have 3 components.
7795  * \param [in] begin start of the nodal connectivity of the face.
7796  * \param [in] end end of the nodal connectivity (excluded) of the face.
7797  * \param [out] v the normalized vector of size 3
7798  * \param [out] p the pos of plane
7799  */
7800 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7801 {
7802   std::size_t nbPoints=std::distance(begin,end);
7803   if(nbPoints<3)
7804     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7805   double vec[3]={0.,0.,0.};
7806   std::size_t j=0;
7807   bool refFound=false;
7808   for(;j<nbPoints-1 && !refFound;j++)
7809     {
7810       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7811       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7812       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7813       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7814       if(norm>eps)
7815         {
7816           refFound=true;
7817           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7818         }
7819     }
7820   for(std::size_t i=j;i<nbPoints-1;i++)
7821     {
7822       double curVec[3];
7823       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7824       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7825       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7826       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7827       if(norm<eps)
7828         continue;
7829       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7830       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];
7831       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7832       if(norm>eps)
7833         {
7834           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7835           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7836           return ;
7837         }
7838     }
7839   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7840 }
7841
7842 /*!
7843  * This method tries to obtain a well oriented polyhedron.
7844  * If the algorithm fails, an exception will be thrown.
7845  */
7846 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7847 {
7848   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7849   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7850   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7851   isPerm[0]=true;
7852   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7853   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7854   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7855   //
7856   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7857     {
7858       bgFace=begin;
7859       std::size_t smthChanged=0;
7860       for(std::size_t i=0;i<nbOfFaces;i++)
7861         {
7862           endFace=std::find(bgFace+1,end,-1);
7863           nbOfEdgesInFace=std::distance(bgFace,endFace);
7864           if(!isPerm[i])
7865             {
7866               bool b;
7867               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7868                 {
7869                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7870                   std::pair<int,int> p2(p1.second,p1.first);
7871                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7872                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7873                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7874                 }
7875               if(isPerm[i])
7876                 { 
7877                   if(!b)
7878                     std::reverse(bgFace+1,endFace);
7879                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7880                     {
7881                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7882                       std::pair<int,int> p2(p1.second,p1.first);
7883                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7884                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7885                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7886                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7887                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7888                       if(it!=edgesOK.end())
7889                         {
7890                           edgesOK.erase(it);
7891                           edgesFinished.push_back(p1);
7892                         }
7893                       else
7894                         edgesOK.push_back(p1);
7895                     }
7896                 }
7897             }
7898           bgFace=endFace+1;
7899         }
7900       if(smthChanged==0)
7901         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7902     }
7903   if(!edgesOK.empty())
7904     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7905   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7906     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7907       bgFace=begin;
7908       for(std::size_t i=0;i<nbOfFaces;i++)
7909         {
7910           endFace=std::find(bgFace+1,end,-1);
7911           std::reverse(bgFace+1,endFace);
7912           bgFace=endFace+1;
7913         }
7914     }
7915 }
7916
7917 /*!
7918  * This method makes the assumption spacedimension == meshdimension == 2.
7919  * This method works only for linear cells.
7920  * 
7921  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7922  */
7923 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7924 {
7925   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7926     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7927   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7928   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7929   int nbOfNodesExpected=m->getNumberOfNodes();
7930   if(m->getNumberOfCells()!=nbOfNodesExpected)
7931     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7932   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7933   const int *n2oPtr=n2o->getConstPointer();
7934   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7935   m->getReverseNodalConnectivity(revNodal,revNodalI);
7936   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7937   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7938   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7939   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7940   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
7941   if(nbOfNodesExpected<1)
7942     return ret.retn();
7943   int prevCell=0;
7944   int prevNode=nodalPtr[nodalIPtr[0]+1];
7945   *work++=n2oPtr[prevNode];
7946   for(int i=1;i<nbOfNodesExpected;i++)
7947     {
7948       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7949         {
7950           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7951           conn.erase(prevNode);
7952           if(conn.size()==1)
7953             {
7954               int curNode=*(conn.begin());
7955               *work++=n2oPtr[curNode];
7956               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7957               shar.erase(prevCell);
7958               if(shar.size()==1)
7959                 {
7960                   prevCell=*(shar.begin());
7961                   prevNode=curNode;
7962                 }
7963               else
7964                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
7965             }
7966           else
7967             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
7968         }
7969       else
7970         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
7971     }
7972   return ret.retn();
7973 }
7974
7975 /*!
7976  * This method makes the assumption spacedimension == meshdimension == 3.
7977  * This method works only for linear cells.
7978  * 
7979  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7980  */
7981 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
7982 {
7983   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7984     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7985   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7986   const int *conn=m->getNodalConnectivity()->getConstPointer();
7987   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
7988   int nbOfCells=m->getNumberOfCells();
7989   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7990   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
7991   if(nbOfCells<1)
7992     return ret.retn();
7993   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7994   for(int i=1;i<nbOfCells;i++)
7995     {
7996       *work++=-1;
7997       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7998     }
7999   return ret.retn();
8000 }
8001
8002 /*!
8003  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8004  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8005  */
8006 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8007 {
8008   double *w=zipFrmt;
8009   if(spaceDim==3)
8010     for(int i=0;i<nbOfNodesInCell;i++)
8011       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8012   else if(spaceDim==2)
8013     {
8014       for(int i=0;i<nbOfNodesInCell;i++)
8015         {
8016           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8017           *w++=0.;
8018         }
8019     }
8020   else
8021     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8022 }
8023
8024 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8025 {
8026   int nbOfCells=getNumberOfCells();
8027   if(nbOfCells<=0)
8028     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8029   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};
8030   ofs << "  <" << getVTKDataSetType() << ">\n";
8031   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8032   ofs << "      <PointData>\n" << pointData << std::endl;
8033   ofs << "      </PointData>\n";
8034   ofs << "      <CellData>\n" << cellData << std::endl;
8035   ofs << "      </CellData>\n";
8036   ofs << "      <Points>\n";
8037   if(getSpaceDimension()==3)
8038     _coords->writeVTK(ofs,8,"Points");
8039   else
8040     {
8041       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8042       coo->writeVTK(ofs,8,"Points");
8043     }
8044   ofs << "      </Points>\n";
8045   ofs << "      <Cells>\n";
8046   const int *cPtr=_nodal_connec->getConstPointer();
8047   const int *cIPtr=_nodal_connec_index->getConstPointer();
8048   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8049   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8050   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8051   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8052   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8053   int szFaceOffsets=0,szConn=0;
8054   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8055     {
8056       *w2=cPtr[cIPtr[i]];
8057       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8058         {
8059           *w1=-1;
8060           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8061           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8062         }
8063       else
8064         {
8065           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8066           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8067           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8068           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8069           w4=std::copy(c.begin(),c.end(),w4);
8070         }
8071     }
8072   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8073   types->writeVTK(ofs,8,"UInt8","types");
8074   offsets->writeVTK(ofs,8,"Int32","offsets");
8075   if(szFaceOffsets!=0)
8076     {//presence of Polyhedra
8077       connectivity->reAlloc(szConn);
8078       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8079       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8080       w1=faces->getPointer();
8081       for(int i=0;i<nbOfCells;i++)
8082         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8083           {
8084             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8085             *w1++=nbFaces;
8086             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8087             for(int j=0;j<nbFaces;j++)
8088               {
8089                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8090                 *w1++=(int)std::distance(w6,w5);
8091                 w1=std::copy(w6,w5,w1);
8092                 w6=w5+1;
8093               }
8094           }
8095       faces->writeVTK(ofs,8,"Int32","faces");
8096     }
8097   connectivity->writeVTK(ofs,8,"Int32","connectivity");
8098   ofs << "      </Cells>\n";
8099   ofs << "    </Piece>\n";
8100   ofs << "  </" << getVTKDataSetType() << ">\n";
8101 }
8102
8103 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8104 {
8105   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8106   if(_mesh_dim==-2)
8107     { stream << " Not set !"; return ; }
8108   stream << " Mesh dimension : " << _mesh_dim << ".";
8109   if(_mesh_dim==-1)
8110     return ;
8111   if(!_coords)
8112     { stream << " No coordinates set !"; return ; }
8113   if(!_coords->isAllocated())
8114     { stream << " Coordinates set but not allocated !"; return ; }
8115   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8116   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8117   if(!_nodal_connec_index)
8118     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8119   if(!_nodal_connec_index->isAllocated())
8120     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8121   int lgth=_nodal_connec_index->getNumberOfTuples();
8122   int cpt=_nodal_connec_index->getNumberOfComponents();
8123   if(cpt!=1 || lgth<1)
8124     return ;
8125   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8126 }
8127
8128 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8129 {
8130   return std::string("UnstructuredGrid");
8131 }
8132
8133 /*!
8134  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8135  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8136  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8137  * meshes.
8138  *  \param [in] m1 - the first input mesh which is a partitioned object.
8139  *  \param [in] m2 - the second input mesh which is a partition tool.
8140  *  \param [in] eps - precision used to detect coincident mesh entities.
8141  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8142  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8143  *         this array using decrRef() as it is no more needed.
8144  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8145  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8146  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8147  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8148  *         it is no more needed.  
8149  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8150  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8151  *         is no more needed.  
8152  *  \throw If the coordinates array is not set in any of the meshes.
8153  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8154  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8155  */
8156 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8157 {
8158   m1->checkFullyDefined();
8159   m2->checkFullyDefined();
8160   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8161     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8162   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8163   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8164   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8165   std::vector<double> addCoo,addCoordsQuadratic;
8166   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8167   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8168   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8169                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8170   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8171   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8172   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8173   std::vector< std::vector<int> > intersectEdge2;
8174   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8175   subDiv2.clear(); dd5=0; dd6=0;
8176   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8177   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8178   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8179                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8180   //
8181   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8182   addCooDa->alloc((int)(addCoo.size())/2,2);
8183   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8184   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8185   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8186   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8187   std::vector<const DataArrayDouble *> coordss(4);
8188   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8189   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8190   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8191   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8192   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8193   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8194   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8195   ret->setConnectivity(conn,connI,true);
8196   ret->setCoords(coo);
8197   cellNb1=c1.retn(); cellNb2=c2.retn();
8198   return ret.retn();
8199 }
8200
8201 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8202                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8203                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8204                                                          const std::vector<double>& addCoords,
8205                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8206 {
8207   static const int SPACEDIM=2;
8208   std::vector<double> bbox1,bbox2;
8209   const double *coo1=m1->getCoords()->getConstPointer();
8210   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8211   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8212   int offset1=m1->getNumberOfNodes();
8213   const double *coo2=m2->getCoords()->getConstPointer();
8214   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8215   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8216   int offset2=offset1+m2->getNumberOfNodes();
8217   int offset3=offset2+((int)addCoords.size())/2;
8218   m1->getBoundingBoxForBBTree(bbox1);
8219   m2->getBoundingBoxForBBTree(bbox2);
8220   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8221   int ncell1=m1->getNumberOfCells();
8222   crI.push_back(0);
8223   for(int i=0;i<ncell1;i++)
8224     {
8225       std::vector<int> candidates2;
8226       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8227       std::map<INTERP_KERNEL::Node *,int> mapp;
8228       std::map<int,INTERP_KERNEL::Node *> mappRev;
8229       INTERP_KERNEL::QuadraticPolygon pol1;
8230       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8231       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8232       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8233       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8234                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8235       //
8236       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
8237       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8238       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8239       for(it1.first();!it1.finished();it1.next())
8240         edges1.insert(it1.current()->getPtr());
8241       //
8242       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8243       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8244       int ii=0;
8245       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8246         {
8247           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8248           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8249           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8250           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8251                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8252         }
8253       ii=0;
8254       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8255         {
8256           pol1.initLocationsWithOther(pol2s[ii]);
8257           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8258           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8259           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8260         }
8261       if(!edges1.empty())
8262         {
8263           try
8264             {
8265               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8266             }
8267           catch(INTERP_KERNEL::Exception& e)
8268             {
8269               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();
8270               throw INTERP_KERNEL::Exception(oss.str().c_str());
8271             }
8272         }
8273       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8274         (*it).second->decrRef();
8275     }
8276 }
8277
8278 /*!
8279  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8280  * 
8281  */
8282 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8283                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8284                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8285                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8286                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8287 {
8288   static const int SPACEDIM=2;
8289   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8290   desc2=DataArrayInt::New();
8291   descIndx2=DataArrayInt::New();
8292   revDesc2=DataArrayInt::New();
8293   revDescIndx2=DataArrayInt::New();
8294   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8295   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8296   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8297   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8298   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8299   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8300   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8301   std::vector<double> bbox1,bbox2;
8302   m1Desc->getBoundingBoxForBBTree(bbox1);
8303   m2Desc->getBoundingBoxForBBTree(bbox2);
8304   int ncell1=m1Desc->getNumberOfCells();
8305   int ncell2=m2Desc->getNumberOfCells();
8306   intersectEdge1.resize(ncell1);
8307   colinear2.resize(ncell2);
8308   subDiv2.resize(ncell2);
8309   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8310   std::vector<int> candidates1(1);
8311   int offset1=m1->getNumberOfNodes();
8312   int offset2=offset1+m2->getNumberOfNodes();
8313   for(int i=0;i<ncell1;i++)
8314     {
8315       std::vector<int> candidates2;
8316       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8317       if(!candidates2.empty())
8318         {
8319           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8320           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8321           candidates1[0]=i;
8322           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8323           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8324           delete pol2;
8325           delete pol1;
8326         }
8327       else
8328         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8329     }
8330   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8331   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8332 }
8333
8334 /*!
8335  * This method performs the 2nd step of Partition of 2D mesh.
8336  * This method has 4 inputs :
8337  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8338  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8339  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8340  * 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'
8341  * \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'
8342  * \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.
8343  * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8344  */
8345 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)
8346 {
8347   int offset1=m1->getNumberOfNodes();
8348   int ncell=m2->getNumberOfCells();
8349   const int *c=m2->getNodalConnectivity()->getConstPointer();
8350   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8351   const double *coo=m2->getCoords()->getConstPointer();
8352   const double *cooBis=m1->getCoords()->getConstPointer();
8353   int offset2=offset1+m2->getNumberOfNodes();
8354   intersectEdge.resize(ncell);
8355   for(int i=0;i<ncell;i++,cI++)
8356     {
8357       const std::vector<int>& divs=subDiv[i];
8358       int nnode=cI[1]-cI[0]-1;
8359       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8360       std::map<INTERP_KERNEL::Node *, int> mapp22;
8361       for(int j=0;j<nnode;j++)
8362         {
8363           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8364           int nnid=c[(*cI)+j+1];
8365           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8366           mapp22[nn]=nnid+offset1;
8367         }
8368       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8369       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8370         ((*it).second.first)->decrRef();
8371       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8372       std::map<INTERP_KERNEL::Node *,int> mapp3;
8373       for(std::size_t j=0;j<divs.size();j++)
8374         {
8375           int id=divs[j];
8376           INTERP_KERNEL::Node *tmp=0;
8377           if(id<offset1)
8378             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8379           else if(id<offset2)
8380             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8381           else
8382             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8383           addNodes[j]=tmp;
8384           mapp3[tmp]=id;
8385         }
8386       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8387       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8388         (*it)->decrRef();
8389       e->decrRef();
8390     }
8391 }
8392
8393 /*!
8394  * 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).
8395  * 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
8396  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8397  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8398  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8399  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8400  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8401  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8402  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8403  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8404  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8405  * \param [out] cut3DSuf input/output param.
8406  */
8407 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8408                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8409                                                    const int *desc, const int *descIndx, 
8410                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8411 {
8412   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8413   int nbOf3DSurfCell=(int)cut3DSurf.size();
8414   for(int i=0;i<nbOf3DSurfCell;i++)
8415     {
8416       std::vector<int> res;
8417       int offset=descIndx[i];
8418       int nbOfSeg=descIndx[i+1]-offset;
8419       for(int j=0;j<nbOfSeg;j++)
8420         {
8421           int edgeId=desc[offset+j];
8422           int status=cut3DCurve[edgeId];
8423           if(status!=-2)
8424             {
8425               if(status>-1)
8426                 res.push_back(status);
8427               else
8428                 {
8429                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8430                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8431                 }
8432             }
8433         }
8434       switch(res.size())
8435         {
8436         case 2:
8437           {
8438             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8439             break;
8440           }
8441         case 1:
8442         case 0:
8443           {
8444             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8445             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8446             if(res.size()==2)
8447               {
8448                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8449               }
8450             else
8451               {
8452                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8453               }
8454             break;
8455           }
8456         default:
8457           {// case when plane is on a multi colinear edge of a polyhedron
8458             if((int)res.size()==2*nbOfSeg)
8459               {
8460                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8461               }
8462             else
8463               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8464           }
8465         }
8466     }
8467 }
8468
8469 /*!
8470  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8471  * 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).
8472  * 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
8473  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8474  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8475  * \param desc is the descending connectivity 3D->3DSurf
8476  * \param descIndx is the descending connectivity index 3D->3DSurf
8477  */
8478 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8479                                                   const int *desc, const int *descIndx,
8480                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8481 {
8482   checkFullyDefined();
8483   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8484     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8485   const int *nodal3D=_nodal_connec->getConstPointer();
8486   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8487   int nbOfCells=getNumberOfCells();
8488   for(int i=0;i<nbOfCells;i++)
8489     {
8490       std::map<int, std::set<int> > m;
8491       int offset=descIndx[i];
8492       int nbOfFaces=descIndx[i+1]-offset;
8493       int start=-1;
8494       int end=-1;
8495       for(int j=0;j<nbOfFaces;j++)
8496         {
8497           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8498           if(p.first!=-1 && p.second!=-1)
8499             {
8500               if(p.first!=-2)
8501                 {
8502                   start=p.first; end=p.second;
8503                   m[p.first].insert(p.second);
8504                   m[p.second].insert(p.first);
8505                 }
8506               else
8507                 {
8508                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8509                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8510                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8511                   INTERP_KERNEL::NormalizedCellType cmsId;
8512                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8513                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8514                   for(unsigned k=0;k<nbOfNodesSon;k++)
8515                     {
8516                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8517                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8518                     }
8519                 }
8520             }
8521         }
8522       if(m.empty())
8523         continue;
8524       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8525       int prev=end;
8526       while(end!=start)
8527         {
8528           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8529           const std::set<int>& s=(*it).second;
8530           std::set<int> s2; s2.insert(prev);
8531           std::set<int> s3;
8532           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8533           if(s3.size()==1)
8534             {
8535               int val=*s3.begin();
8536               conn.push_back(start);
8537               prev=start;
8538               start=val;
8539             }
8540           else
8541             start=end;
8542         }
8543       conn.push_back(end);
8544       if(conn.size()>3)
8545         {
8546           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8547           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8548           cellIds->pushBackSilent(i);
8549         }
8550     }
8551 }
8552
8553 /*!
8554  * 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
8555  * 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
8556  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8557  * 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
8558  * 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.
8559  * 
8560  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8561  */
8562 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8563 {
8564   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8565   if(sz>=4)
8566     {
8567       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8568       if(cm.getDimension()==2)
8569         {
8570           const int *node=nodalConnBg+1;
8571           int startNode=*node++;
8572           double refX=coords[2*startNode];
8573           for(;node!=nodalConnEnd;node++)
8574             {
8575               if(coords[2*(*node)]<refX)
8576                 {
8577                   startNode=*node;
8578                   refX=coords[2*startNode];
8579                 }
8580             }
8581           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8582           refX=1e300;
8583           double tmp1;
8584           double tmp2[2];
8585           double angle0=-M_PI/2;
8586           //
8587           int nextNode=-1;
8588           int prevNode=-1;
8589           double resRef;
8590           double angleNext=0.;
8591           while(nextNode!=startNode)
8592             {
8593               nextNode=-1;
8594               resRef=1e300;
8595               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8596                 {
8597                   if(*node!=tmpOut.back() && *node!=prevNode)
8598                     {
8599                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8600                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8601                       double res;
8602                       if(angleM<=angle0)
8603                         res=angle0-angleM;
8604                       else
8605                         res=angle0-angleM+2.*M_PI;
8606                       if(res<resRef)
8607                         {
8608                           nextNode=*node;
8609                           resRef=res;
8610                           angleNext=angleM;
8611                         }
8612                     }
8613                 }
8614               if(nextNode!=startNode)
8615                 {
8616                   angle0=angleNext-M_PI;
8617                   if(angle0<-M_PI)
8618                     angle0+=2*M_PI;
8619                   prevNode=tmpOut.back();
8620                   tmpOut.push_back(nextNode);
8621                 }
8622             }
8623           std::vector<int> tmp3(2*(sz-1));
8624           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8625           std::copy(nodalConnBg+1,nodalConnEnd,it);
8626           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8627             {
8628               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8629               return false;
8630             }
8631           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8632             {
8633               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8634               return false;
8635             }
8636           else
8637             {
8638               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8639               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8640               return true;
8641             }
8642         }
8643       else
8644         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8645     }
8646   else
8647     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8648 }
8649
8650 /*!
8651  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8652  * 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.
8653  * 
8654  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8655  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8656  * \param [in,out] arr array in which the remove operation will be done.
8657  * \param [in,out] arrIndx array in the remove operation will modify
8658  * \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])
8659  * \return true if \b arr and \b arrIndx have been modified, false if not.
8660  */
8661 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8662 {
8663   if(!arrIndx || !arr)
8664     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8665   if(offsetForRemoval<0)
8666     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8667   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8668   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8669   int *arrIPtr=arrIndx->getPointer();
8670   *arrIPtr++=0;
8671   int previousArrI=0;
8672   const int *arrPtr=arr->getConstPointer();
8673   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8674   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8675     {
8676       if(*arrIPtr-previousArrI>offsetForRemoval)
8677         {
8678           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8679             {
8680               if(s.find(*work)==s.end())
8681                 arrOut.push_back(*work);
8682             }
8683         }
8684       previousArrI=*arrIPtr;
8685       *arrIPtr=(int)arrOut.size();
8686     }
8687   if(arr->getNumberOfTuples()==(int)arrOut.size())
8688     return false;
8689   arr->alloc((int)arrOut.size(),1);
8690   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8691   return true;
8692 }
8693
8694 /*!
8695  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8696  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8697  * The selection of extraction is done standardly in new2old format.
8698  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8699  *
8700  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8701  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8702  * \param [in] arrIn arr origin array from which the extraction will be done.
8703  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8704  * \param [out] arrOut the resulting array
8705  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8706  */
8707 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8708                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8709 {
8710   if(!arrIn || !arrIndxIn)
8711     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8712   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8713   const int *arrInPtr=arrIn->getConstPointer();
8714   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8715   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8716   int maxSizeOfArr=arrIn->getNumberOfTuples();
8717   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8718   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8719   arrIo->alloc((int)(sz+1),1);
8720   const int *idsIt=idsOfSelectBg;
8721   int *work=arrIo->getPointer();
8722   *work++=0;
8723   int lgth=0;
8724   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8725     {
8726       if(*idsIt>=0 && *idsIt<nbOfGrps)
8727         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8728       else
8729         {
8730           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8731           throw INTERP_KERNEL::Exception(oss.str().c_str());
8732         }
8733       if(lgth>=work[-1])
8734         *work=lgth;
8735       else
8736         {
8737           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8738           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8739           throw INTERP_KERNEL::Exception(oss.str().c_str());
8740         }
8741     }
8742   arro->alloc(lgth,1);
8743   work=arro->getPointer();
8744   idsIt=idsOfSelectBg;
8745   for(std::size_t i=0;i<sz;i++,idsIt++)
8746     {
8747       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8748         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8749       else
8750         {
8751           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8752           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8753           throw INTERP_KERNEL::Exception(oss.str().c_str());
8754         }
8755     }
8756   arrOut=arro.retn();
8757   arrIndexOut=arrIo.retn();
8758 }
8759
8760 /*!
8761  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8762  * 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
8763  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8764  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8765  *
8766  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8767  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8768  * \param [in] arrIn arr origin array from which the extraction will be done.
8769  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8770  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8771  * \param [in] srcArrIndex index array of \b srcArr
8772  * \param [out] arrOut the resulting array
8773  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8774  * 
8775  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8776  */
8777 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8778                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8779                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8780 {
8781   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8782     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8783   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8784   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8785   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8786   std::vector<bool> v(nbOfTuples,true);
8787   int offset=0;
8788   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8789   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8790   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8791     {
8792       if(*it>=0 && *it<nbOfTuples)
8793         {
8794           v[*it]=false;
8795           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8796         }
8797       else
8798         {
8799           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8800           throw INTERP_KERNEL::Exception(oss.str().c_str());
8801         }
8802     }
8803   srcArrIndexPtr=srcArrIndex->getConstPointer();
8804   arrIo->alloc(nbOfTuples+1,1);
8805   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8806   const int *arrInPtr=arrIn->getConstPointer();
8807   const int *srcArrPtr=srcArr->getConstPointer();
8808   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8809   int *arroPtr=arro->getPointer();
8810   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8811     {
8812       if(v[ii])
8813         {
8814           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8815           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8816         }
8817       else
8818         {
8819           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8820           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8821           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8822         }
8823     }
8824   arrOut=arro.retn();
8825   arrIndexOut=arrIo.retn();
8826 }
8827
8828 /*!
8829  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8830  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8831  *
8832  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8833  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8834  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8835  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8836  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8837  * \param [in] srcArrIndex index array of \b srcArr
8838  * 
8839  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8840  */
8841 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8842                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8843 {
8844   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8845     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8846   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8847   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8848   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8849   int *arrInOutPtr=arrInOut->getPointer();
8850   const int *srcArrPtr=srcArr->getConstPointer();
8851   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8852     {
8853       if(*it>=0 && *it<nbOfTuples)
8854         {
8855           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8856             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8857           else
8858             {
8859               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] !";
8860               throw INTERP_KERNEL::Exception(oss.str().c_str());
8861             }
8862         }
8863       else
8864         {
8865           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8866           throw INTERP_KERNEL::Exception(oss.str().c_str());
8867         }
8868     }
8869 }
8870
8871 /*!
8872  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8873  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8874  * 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]].
8875  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8876  * A negative value in \b arrIn means that it is ignored.
8877  * 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.
8878  * 
8879  * \param [in] arrIn arr origin array from which the extraction will be done.
8880  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8881  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8882  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8883  */
8884 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
8885 {
8886   int seed=0,nbOfDepthPeelingPerformed=0;
8887   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8888 }
8889
8890 /*!
8891  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8892  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8893  * 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]].
8894  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8895  * A negative value in \b arrIn means that it is ignored.
8896  * 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.
8897  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8898  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8899  * \param [in] arrIn arr origin array from which the extraction will be done.
8900  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8901  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8902  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8903  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8904  * \sa MEDCouplingUMesh::partitionBySpreadZone
8905  */
8906 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8907 {
8908   nbOfDepthPeelingPerformed=0;
8909   if(!arrIndxIn)
8910     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8911   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8912   if(nbOfTuples<=0)
8913     {
8914       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8915       return ret;
8916     }
8917   //
8918   std::vector<bool> fetched(nbOfTuples,false);
8919   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8920 }
8921
8922 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)
8923 {
8924   nbOfDepthPeelingPerformed=0;
8925   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
8926     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
8927   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8928   std::vector<bool> fetched2(nbOfTuples,false);
8929   int i=0;
8930   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
8931     {
8932       if(*seedElt>=0 && *seedElt<nbOfTuples)
8933         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
8934       else
8935         { 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()); }
8936     }
8937   const int *arrInPtr=arrIn->getConstPointer();
8938   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8939   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
8940   std::vector<int> idsToFetch1(seedBg,seedEnd);
8941   std::vector<int> idsToFetch2;
8942   std::vector<int> *idsToFetch=&idsToFetch1;
8943   std::vector<int> *idsToFetchOther=&idsToFetch2;
8944   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
8945     {
8946       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
8947         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
8948           if(!fetched[*it2])
8949             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
8950       std::swap(idsToFetch,idsToFetchOther);
8951       idsToFetchOther->clear();
8952       nbOfDepthPeelingPerformed++;
8953     }
8954   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
8955   i=0;
8956   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
8957   int *retPtr=ret->getPointer();
8958   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
8959     if(*it)
8960       *retPtr++=i;
8961   return ret.retn();
8962 }
8963
8964 /*!
8965  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8966  * 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
8967  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8968  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8969  *
8970  * \param [in] start begin of set of ids of the input extraction (included)
8971  * \param [in] end end of set of ids of the input extraction (excluded)
8972  * \param [in] step step of the set of ids in range mode.
8973  * \param [in] arrIn arr origin array from which the extraction will be done.
8974  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8975  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8976  * \param [in] srcArrIndex index array of \b srcArr
8977  * \param [out] arrOut the resulting array
8978  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8979  * 
8980  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8981  */
8982 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8983                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8984                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8985 {
8986   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8987     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
8988   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8989   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8990   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8991   int offset=0;
8992   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8993   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8994   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
8995   int it=start;
8996   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8997     {
8998       if(it>=0 && it<nbOfTuples)
8999         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9000       else
9001         {
9002           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9003           throw INTERP_KERNEL::Exception(oss.str().c_str());
9004         }
9005     }
9006   srcArrIndexPtr=srcArrIndex->getConstPointer();
9007   arrIo->alloc(nbOfTuples+1,1);
9008   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9009   const int *arrInPtr=arrIn->getConstPointer();
9010   const int *srcArrPtr=srcArr->getConstPointer();
9011   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9012   int *arroPtr=arro->getPointer();
9013   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9014     {
9015       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9016       if(pos<0)
9017         {
9018           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9019           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9020         }
9021       else
9022         {
9023           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9024           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9025         }
9026     }
9027   arrOut=arro.retn();
9028   arrIndexOut=arrIo.retn();
9029 }
9030
9031 /*!
9032  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9033  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9034  *
9035  * \param [in] start begin of set of ids of the input extraction (included)
9036  * \param [in] end end of set of ids of the input extraction (excluded)
9037  * \param [in] step step of the set of ids in range mode.
9038  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9039  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9040  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9041  * \param [in] srcArrIndex index array of \b srcArr
9042  * 
9043  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9044  */
9045 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9046                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9047 {
9048   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9049     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9050   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9051   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9052   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9053   int *arrInOutPtr=arrInOut->getPointer();
9054   const int *srcArrPtr=srcArr->getConstPointer();
9055   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9056   int it=start;
9057   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9058     {
9059       if(it>=0 && it<nbOfTuples)
9060         {
9061           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9062             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9063           else
9064             {
9065               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9066               throw INTERP_KERNEL::Exception(oss.str().c_str());
9067             }
9068         }
9069       else
9070         {
9071           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9072           throw INTERP_KERNEL::Exception(oss.str().c_str());
9073         }
9074     }
9075 }
9076
9077 /*!
9078  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9079  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9080  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9081  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9082  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9083  * 
9084  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9085  */
9086 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9087 {
9088   checkFullyDefined();
9089   int mdim=getMeshDimension();
9090   int spaceDim=getSpaceDimension();
9091   if(mdim!=spaceDim)
9092     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9093   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9094   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9095   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9096   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9097   ret->setCoords(getCoords());
9098   ret->allocateCells((int)partition.size());
9099   //
9100   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9101     {
9102       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9103       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9104       switch(mdim)
9105         {
9106         case 2:
9107           cell=tmp->buildUnionOf2DMesh();
9108           break;
9109         case 3:
9110           cell=tmp->buildUnionOf3DMesh();
9111           break;
9112         default:
9113           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9114         }
9115       
9116       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9117     }
9118   //
9119   ret->finishInsertingCells();
9120   return ret.retn();
9121 }
9122
9123 /*!
9124  * This method partitions \b this into contiguous zone.
9125  * This method only needs a well defined connectivity. Coordinates are not considered here.
9126  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9127  */
9128 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9129 {
9130   //#if 0
9131   int nbOfCellsCur=getNumberOfCells();
9132   std::vector<DataArrayInt *> ret;
9133   if(nbOfCellsCur<=0)
9134     return ret;
9135   DataArrayInt *neigh=0,*neighI=0;
9136   computeNeighborsOfCells(neigh,neighI);
9137   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9138   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9139   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9140   int seed=0;
9141   while(seed<nbOfCellsCur)
9142     {
9143       int nbOfPeelPerformed=0;
9144       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9145       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9146     }
9147   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9148     ret.push_back((*it).retn());
9149   return ret;
9150   //#endif
9151 #if 0
9152   int nbOfCellsCur=getNumberOfCells();
9153   DataArrayInt *neigh=0,*neighI=0;
9154   computeNeighborsOfCells(neigh,neighI);
9155   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9156   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9157   std::vector<DataArrayInt *> ret;
9158   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9159   while(nbOfCellsCur>0)
9160     {
9161       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9162       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9163       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9164       ret2.push_back(tmp2);  ret.push_back(tmp2);
9165       nbOfCellsCur=tmp3->getNumberOfTuples();
9166       if(nbOfCellsCur>0)
9167         {
9168           ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9169           MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9170           neighAuto=neigh;
9171           neighIAuto=neighI;
9172           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9173           neighAuto->transformWithIndArr(renum->begin(),renum->end());
9174         }
9175     }
9176   for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9177     (*it)->incrRef();
9178   return ret;
9179 #endif
9180 }
9181
9182 /*!
9183  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9184  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9185  *
9186  * \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.
9187  * \return a newly allocated DataArrayInt to be managed by the caller.
9188  * \throw In case of \a code has not the right format (typically of size 3*n)
9189  */
9190 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9191 {
9192   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9193   std::size_t nb=code.size()/3;
9194   if(code.size()%3!=0)
9195     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9196   ret->alloc((int)nb,2);
9197   int *retPtr=ret->getPointer();
9198   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9199     {
9200       retPtr[0]=code[3*i+2];
9201       retPtr[1]=code[3*i+2]+code[3*i+1];
9202     }
9203   return ret.retn();
9204 }
9205
9206 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9207                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9208 {
9209   if(mesh)
9210     {
9211       mesh->incrRef();
9212       _nb_cell=mesh->getNumberOfCells();
9213     }
9214 }
9215
9216 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9217 {
9218   if(_mesh)
9219     _mesh->decrRef();
9220   if(_own_cell)
9221     delete _cell;
9222 }
9223
9224 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9225                                                                                                                                _own_cell(false),_cell_id(bg-1),
9226                                                                                                                                _nb_cell(end)
9227 {
9228   if(mesh)
9229     mesh->incrRef();
9230 }
9231
9232 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9233 {
9234   _cell_id++;
9235   if(_cell_id<_nb_cell)
9236     {
9237       _cell->next();
9238       return _cell;
9239     }
9240   else
9241     return 0;
9242 }
9243
9244 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9245 {
9246   if(_mesh)
9247     _mesh->incrRef();
9248 }
9249
9250 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9251 {
9252   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9253 }
9254
9255 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9256 {
9257   if(_mesh)
9258     _mesh->decrRef();
9259 }
9260
9261 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9262                                                                                                                                                                   _itc(itc),
9263                                                                                                                                                                   _bg(bg),_end(end)
9264 {
9265   if(_mesh)
9266     _mesh->incrRef();
9267 }
9268
9269 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9270 {
9271   if(_mesh)
9272     _mesh->decrRef();
9273 }
9274
9275 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9276 {
9277   return _type;
9278 }
9279
9280 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9281 {
9282   return _end-_bg;
9283 }
9284
9285 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9286 {
9287   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9288 }
9289
9290 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9291 {
9292   if(mesh)
9293     {
9294       mesh->incrRef();
9295       _nb_cell=mesh->getNumberOfCells();
9296     }
9297 }
9298
9299 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9300 {
9301   if(_mesh)
9302     _mesh->decrRef();
9303   delete _cell;
9304 }
9305
9306 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9307 {
9308   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9309   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9310   if(_cell_id<_nb_cell)
9311     {
9312       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9313       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9314       int startId=_cell_id;
9315       _cell_id+=nbOfElems;
9316       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9317     }
9318   else
9319     return 0;
9320 }
9321
9322 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9323 {
9324   if(mesh)
9325     {
9326       _conn=mesh->getNodalConnectivity()->getPointer();
9327       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9328     }
9329 }
9330
9331 void MEDCouplingUMeshCell::next()
9332 {
9333   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9334     {
9335       _conn+=_conn_lgth;
9336       _conn_indx++;
9337     }
9338   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9339 }
9340
9341 std::string MEDCouplingUMeshCell::repr() const
9342 {
9343   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9344     {
9345       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9346       oss << " : ";
9347       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9348       return oss.str();
9349     }
9350   else
9351     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9352 }
9353
9354 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9355 {
9356   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9357     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9358   else
9359     return INTERP_KERNEL::NORM_ERROR;
9360 }
9361
9362 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9363 {
9364   lgth=_conn_lgth;
9365   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9366     return _conn;
9367   else
9368     return 0;
9369 }