Salome HOME
More checks in profiles computation
[modules/med.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMeshQuality.hxx"
34 #include "InterpKernelCellSimplify.hxx"
35 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
36 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
42
43 #include <sstream>
44 #include <fstream>
45 #include <numeric>
46 #include <cstring>
47 #include <limits>
48 #include <list>
49
50 using namespace ParaMEDMEM;
51
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53
54 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
55
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 {
58   return new MEDCouplingUMesh;
59 }
60
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
62 {
63   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64   ret->setName(meshName);
65   ret->setMeshDimension(meshDim);
66   return ret;
67 }
68
69 /*!
70  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71  * between \a this and the new mesh.
72  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73  *          delete this mesh using decrRef() as it is no more needed. 
74  */
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
76 {
77   return clone(true);
78 }
79
80 /*!
81  * Returns a new MEDCouplingMesh which is a copy of \a this one.
82  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83  * this mesh are shared by the new mesh.
84  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85  *          delete this mesh using decrRef() as it is no more needed. 
86  */
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
88 {
89   return new MEDCouplingUMesh(*this,recDeepCpy);
90 }
91
92 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other) throw(INTERP_KERNEL::Exception)
93 {
94   if(!other)
95     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
96   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
97   if(!otherC)
98     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
99   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
100   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
101 }
102
103 std::size_t MEDCouplingUMesh::getHeapMemorySize() const
104 {
105   std::size_t ret=0;
106   if(_nodal_connec)
107     ret+=_nodal_connec->getHeapMemorySize();
108   if(_nodal_connec_index)
109     ret+=_nodal_connec_index->getHeapMemorySize();
110   return MEDCouplingPointSet::getHeapMemorySize()+ret;
111 }
112
113 void MEDCouplingUMesh::updateTime() const
114 {
115   MEDCouplingPointSet::updateTime();
116   if(_nodal_connec)
117     {
118       updateTimeWith(*_nodal_connec);
119     }
120   if(_nodal_connec_index)
121     {
122       updateTimeWith(*_nodal_connec_index);
123     }
124 }
125
126 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
127 {
128 }
129
130 /*!
131  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
132  * then \a this mesh is most probably is writable, exchangeable and available for most
133  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
134  * this method to check that all is in order with \a this mesh.
135  *  \throw If the mesh dimension is not set.
136  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
137  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
138  *  \throw If the connectivity data array has more than one component.
139  *  \throw If the connectivity data array has a named component.
140  *  \throw If the connectivity index data array has more than one component.
141  *  \throw If the connectivity index data array has a named component.
142  */
143 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
144 {
145   if(_mesh_dim<-1)
146    throw INTERP_KERNEL::Exception("No mesh dimension specified !");
147   if(_mesh_dim!=-1)
148     MEDCouplingPointSet::checkCoherency();
149   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
150     {
151       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
152         {
153           std::ostringstream message;
154           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
155           throw INTERP_KERNEL::Exception(message.str().c_str());
156         }
157     }
158   if(_nodal_connec)
159     {
160       if(_nodal_connec->getNumberOfComponents()!=1)
161         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
162       if(_nodal_connec->getInfoOnComponent(0)!="")
163         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
164     }
165   else
166     if(_mesh_dim!=-1)
167       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
168   if(_nodal_connec_index)
169     {
170       if(_nodal_connec_index->getNumberOfComponents()!=1)
171         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
172       if(_nodal_connec_index->getInfoOnComponent(0)!="")
173         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
174     }
175   else
176     if(_mesh_dim!=-1)
177       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
178 }
179
180 /*!
181  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
182  * then \a this mesh is most probably is writable, exchangeable and available for all
183  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
184  * method thoroughly checks the nodal connectivity.
185  *  \param [in] eps - a not used parameter.
186  *  \throw If the mesh dimension is not set.
187  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
188  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
189  *  \throw If the connectivity data array has more than one component.
190  *  \throw If the connectivity data array has a named component.
191  *  \throw If the connectivity index data array has more than one component.
192  *  \throw If the connectivity index data array has a named component.
193  *  \throw If number of nodes defining an element does not correspond to the type of element.
194  *  \throw If the nodal connectivity includes an invalid node id.
195  */
196 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
197 {
198   checkCoherency();
199   if(_mesh_dim==-1)
200     return ;
201   int meshDim=getMeshDimension();
202   int nbOfNodes=getNumberOfNodes();
203   int nbOfCells=getNumberOfCells();
204   const int *ptr=_nodal_connec->getConstPointer();
205   const int *ptrI=_nodal_connec_index->getConstPointer();
206   for(int i=0;i<nbOfCells;i++)
207     {
208       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
209       if((int)cm.getDimension()!=meshDim)
210         {
211           std::ostringstream oss;
212           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
213           throw INTERP_KERNEL::Exception(oss.str().c_str());
214         }
215       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
216       if(!cm.isDynamic())
217         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
218           {
219             std::ostringstream oss;
220             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
221             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
222             throw INTERP_KERNEL::Exception(oss.str().c_str());
223           }
224       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
225         {
226           int nodeId=*w;
227           if(nodeId>=0)
228             {
229               if(nodeId>=nbOfNodes)
230                 {
231                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
232                   throw INTERP_KERNEL::Exception(oss.str().c_str());
233                 }
234             }
235           else if(nodeId<-1)
236             {
237               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
238               throw INTERP_KERNEL::Exception(oss.str().c_str());
239             }
240           else
241             {
242               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
243                 {
244                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
245                   throw INTERP_KERNEL::Exception(oss.str().c_str());
246                 }
247             }
248         }
249     }
250 }
251
252
253 /*!
254  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
255  * then \a this mesh is most probably is writable, exchangeable and available for all
256  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
257  *  \param [in] eps - a not used parameter.
258  *  \throw If the mesh dimension is not set.
259  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
260  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
261  *  \throw If the connectivity data array has more than one component.
262  *  \throw If the connectivity data array has a named component.
263  *  \throw If the connectivity index data array has more than one component.
264  *  \throw If the connectivity index data array has a named component.
265  *  \throw If number of nodes defining an element does not correspond to the type of element.
266  *  \throw If the nodal connectivity includes an invalid node id.
267  */
268 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
269 {
270   checkCoherency1(eps);
271 }
272
273 /*!
274  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
275  * elements contained in the mesh. For more info on the mesh dimension see
276  * \ref MEDCouplingUMeshPage.
277  *  \param [in] meshDim - a new mesh dimension.
278  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
279  */
280 void MEDCouplingUMesh::setMeshDimension(int meshDim)
281 {
282   if(meshDim<-1 || meshDim>3)
283     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
284   _mesh_dim=meshDim;
285   declareAsNew();
286 }
287
288 /*!
289  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
290  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
291  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
292  *
293  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
294  *
295  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
296  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
297  */
298 void MEDCouplingUMesh::allocateCells(int nbOfCells)
299 {
300   if(nbOfCells<0)
301     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
302   if(_nodal_connec_index)
303     {
304       _nodal_connec_index->decrRef();
305     }
306   if(_nodal_connec)
307     {
308       _nodal_connec->decrRef();
309     }
310   _nodal_connec_index=DataArrayInt::New();
311   _nodal_connec_index->reserve(nbOfCells+1);
312   _nodal_connec_index->pushBackSilent(0);
313   _nodal_connec=DataArrayInt::New();
314   _nodal_connec->reserve(2*nbOfCells);
315   _types.clear();
316   declareAsNew();
317 }
318
319 /*!
320  * Appends a cell to the connectivity array. For deeper understanding what is
321  * happening see \ref MEDCouplingUMeshNodalConnectivity.
322  *  \param [in] type - type of cell to add.
323  *  \param [in] size - number of nodes constituting this cell.
324  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
325  * 
326  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
327  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
328  */
329 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
330 {
331   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
332   if(_nodal_connec_index==0)
333     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
334   if((int)cm.getDimension()==_mesh_dim)
335     {
336       if(!cm.isDynamic())
337         if(size!=(int)cm.getNumberOfNodes())
338           {
339             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
340             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
341             throw INTERP_KERNEL::Exception(oss.str().c_str());
342           }
343       int idx=_nodal_connec_index->back();
344       int val=idx+size+1;
345       _nodal_connec_index->pushBackSilent(val);
346       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
347       _types.insert(type);
348     }
349   else
350     {
351       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
352       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
353       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
354       throw INTERP_KERNEL::Exception(oss.str().c_str());
355     }
356 }
357
358 /*!
359  * Compacts data arrays to release unused memory. This method is to be called after
360  * finishing cell insertion using \a this->insertNextCell().
361  * 
362  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
363  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
364  */
365 void MEDCouplingUMesh::finishInsertingCells()
366 {
367   _nodal_connec->pack();
368   _nodal_connec_index->pack();
369   _nodal_connec->declareAsNew();
370   _nodal_connec_index->declareAsNew();
371   updateTime();
372 }
373
374 /*!
375  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
376  * Useful for python users.
377  */
378 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
379 {
380   return new MEDCouplingUMeshCellIterator(this);
381 }
382
383 /*!
384  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
385  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
386  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
387  * Useful for python users.
388  */
389 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
390 {
391   if(!checkConsecutiveCellTypes())
392     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
393   return new MEDCouplingUMeshCellByTypeEntry(this);
394 }
395
396 /*!
397  * Returns a set of all cell types available in \a this mesh.
398  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
399  * \warning this method does not throw any exception even if \a this is not defined.
400  */
401 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
402 {
403   return _types;
404 }
405
406 /*!
407  * This method is a method that compares \a this and \a other.
408  * This method compares \b all attributes, even names and component names.
409  */
410 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
411 {
412   if(!other)
413     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
414   std::ostringstream oss; oss.precision(15);
415   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
416   if(!otherC)
417     {
418       reason="mesh given in input is not castable in MEDCouplingUMesh !";
419       return false;
420     }
421   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
422     return false;
423   if(_mesh_dim!=otherC->_mesh_dim)
424     {
425       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
426       reason=oss.str();
427       return false;
428     }
429   if(_types!=otherC->_types)
430     {
431       oss << "umesh geometric type mismatch :\nThis geometric types are :";
432       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
433         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
434       oss << "\nOther geometric types are :";
435       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
436         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
437       reason=oss.str();
438       return false;
439     }
440   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
441     if(_nodal_connec==0 || otherC->_nodal_connec==0)
442       {
443         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
444         return false;
445       }
446   if(_nodal_connec!=otherC->_nodal_connec)
447     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
448       {
449         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
450         return false;
451       }
452   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
453     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
454       {
455         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
456         return false;
457       }
458   if(_nodal_connec_index!=otherC->_nodal_connec_index)
459     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
460       {
461         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
462         return false;
463       }
464   return true;
465 }
466
467 /*!
468  * Checks if data arrays of this mesh (node coordinates, nodal
469  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
470  * not considered.
471  *  \param [in] other - the mesh to compare with.
472  *  \param [in] prec - precision value used to compare node coordinates.
473  *  \return bool - \a true if the two meshes are same.
474  */
475 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
476 {
477   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
478   if(!otherC)
479     return false;
480   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
481     return false;
482   if(_mesh_dim!=otherC->_mesh_dim)
483     return false;
484   if(_types!=otherC->_types)
485     return false;
486   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
487     if(_nodal_connec==0 || otherC->_nodal_connec==0)
488       return false;
489   if(_nodal_connec!=otherC->_nodal_connec)
490     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
491       return false;
492   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
493     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
494       return false;
495   if(_nodal_connec_index!=otherC->_nodal_connec_index)
496     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
497       return false;
498   return true;
499 }
500
501 /*!
502  * Checks if \a this and \a other meshes are geometrically equivalent with high
503  * probability, else an exception is thrown. The meshes are considered equivalent if
504  * (1) meshes contain the same number of nodes and the same number of elements of the
505  * same types (2) three cells of the two meshes (first, last and middle) are based
506  * on coincident nodes (with a specified precision).
507  *  \param [in] other - the mesh to compare with.
508  *  \param [in] prec - the precision used to compare nodes of the two meshes.
509  *  \throw If the two meshes do not match.
510  */
511 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
512 {
513  MEDCouplingPointSet::checkFastEquivalWith(other,prec);
514  const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
515   if(!otherC)
516     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
517 }
518
519 /*!
520  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
521  * cells each node belongs to.
522  * \warning For speed reasons, this method does not check if node ids in the nodal
523  *          connectivity correspond to the size of node coordinates array.
524  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
525  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
526  *        dividing cell ids in \a revNodal into groups each referring to one
527  *        node. Its every element (except the last one) is an index pointing to the
528  *         first id of a group of cells. For example cells sharing the node #1 are 
529  *        described by following range of indices: 
530  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
531  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
532  *        Number of cells sharing the *i*-th node is
533  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
534  * \throw If the coordinates array is not set.
535  * \throw If the nodal connectivity of cells is not defined.
536  * 
537  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
538  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
539  */
540 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
541 {
542   checkFullyDefined();
543   int nbOfNodes=getNumberOfNodes();
544   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
545   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
546   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
547   const int *conn=_nodal_connec->getConstPointer();
548   const int *connIndex=_nodal_connec_index->getConstPointer();
549   int nbOfCells=getNumberOfCells();
550   int nbOfEltsInRevNodal=0;
551   for(int eltId=0;eltId<nbOfCells;eltId++)
552     {
553       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
554       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
555       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
556         if(*iter>=0)//for polyhedrons
557           {
558             nbOfEltsInRevNodal++;
559             revNodalIndxPtr[(*iter)+1]++;
560           }
561     }
562   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
563   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
564   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
565   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
566   for(int eltId=0;eltId<nbOfCells;eltId++)
567     {
568       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
569       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
570       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
571         if(*iter>=0)//for polyhedrons
572           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
573     }
574 }
575
576 /// @cond INTERNAL
577
578 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
579 {
580   return id;
581 }
582
583 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
584 {
585   if(!compute)
586     return id+1;
587   else
588     {
589       if(cm.getOrientationStatus(nb,conn1,conn2))
590         return id+1;
591       else
592         return -(id+1);
593     }
594 }
595
596 class MinusOneSonsGenerator
597 {
598 public:
599   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
600   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
601   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
602   static const int DELTA=1;
603 private:
604   const INTERP_KERNEL::CellModel& _cm;
605 };
606
607 class MinusOneSonsGeneratorBiQuadratic
608 {
609 public:
610   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
611   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
612   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
613   static const int DELTA=1;
614 private:
615   const INTERP_KERNEL::CellModel& _cm;
616 };
617
618 class MinusTwoSonsGenerator
619 {
620 public:
621   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
622   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
623   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
624   static const int DELTA=2;
625 private:
626   const INTERP_KERNEL::CellModel& _cm;
627 };
628
629 /// @endcond
630
631 /*!
632  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
633  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
634  * describing correspondence between cells of \a this and the result meshes are
635  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
636  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
637  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
638  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
639  * \warning For speed reasons, this method does not check if node ids in the nodal
640  *          connectivity correspond to the size of node coordinates array.
641  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
642  *          to write this mesh to the MED file, its cells must be sorted using
643  *          sortCellsInMEDFileFrmt().
644  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
645  *         each cell of \a this mesh.
646  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
647  *        dividing cell ids in \a desc into groups each referring to one
648  *        cell of \a this mesh. Its every element (except the last one) is an index
649  *        pointing to the first id of a group of cells. For example cells of the
650  *        result mesh bounding the cell #1 of \a this mesh are described by following
651  *        range of indices:
652  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
653  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
654  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
655  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
656  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
657  *         by each cell of the result mesh.
658  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
659  *        in the result mesh,
660  *        dividing cell ids in \a revDesc into groups each referring to one
661  *        cell of the result mesh the same way as \a descIndx divides \a desc.
662  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
663  *        delete this mesh using decrRef() as it is no more needed.
664  *  \throw If the coordinates array is not set.
665  *  \throw If the nodal connectivity of cells is node defined.
666  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
667  *         revDescIndx == NULL.
668  * 
669  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
670  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
671  * \sa buildDescendingConnectivity2()
672  */
673 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
674 {
675   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
676 }
677
678 /*!
679  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
680  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
681  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
682  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
683  * \sa MEDCouplingUMesh::buildDescendingConnectivity
684  */
685 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
686 {
687   checkFullyDefined();
688   if(getMeshDimension()!=3)
689     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
690   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
691 }
692
693 /*!
694  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
695  * this->getMeshDimension(), that bound cells of \a this mesh. In
696  * addition arrays describing correspondence between cells of \a this and the result
697  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
698  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
699  *  mesh. This method differs from buildDescendingConnectivity() in that apart
700  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
701  * result meshes. So a positive id means that order of nodes in corresponding cells
702  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
703  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
704  * i.e. cell ids are one-based.
705  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
706  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
707  * \warning For speed reasons, this method does not check if node ids in the nodal
708  *          connectivity correspond to the size of node coordinates array.
709  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
710  *          to write this mesh to the MED file, its cells must be sorted using
711  *          sortCellsInMEDFileFrmt().
712  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
713  *         each cell of \a this mesh.
714  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
715  *        dividing cell ids in \a desc into groups each referring to one
716  *        cell of \a this mesh. Its every element (except the last one) is an index
717  *        pointing to the first id of a group of cells. For example cells of the
718  *        result mesh bounding the cell #1 of \a this mesh are described by following
719  *        range of indices:
720  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
721  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
722  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
723  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
724  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
725  *         by each cell of the result mesh.
726  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
727  *        in the result mesh,
728  *        dividing cell ids in \a revDesc into groups each referring to one
729  *        cell of the result mesh the same way as \a descIndx divides \a desc.
730  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
731  *        shares the node coordinates array with \a this mesh. The caller is to
732  *        delete this mesh using decrRef() as it is no more needed.
733  *  \throw If the coordinates array is not set.
734  *  \throw If the nodal connectivity of cells is node defined.
735  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
736  *         revDescIndx == NULL.
737  * 
738  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
739  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
740  * \sa buildDescendingConnectivity()
741  */
742 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
743 {
744   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
745 }
746
747 /*!
748  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
749  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
750  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
751  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
752  *
753  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
754  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
755  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
756  */
757 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
758 {
759   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
761   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
762   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
763   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
764   meshDM1=0;
765   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
766 }
767
768 /*!
769  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
770  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
771  * excluding a set of meshdim-1 cells in input descending connectivity.
772  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
773  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
774  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
775  *
776  * \param [in] desc descending connectivity array.
777  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
778  * \param [in] revDesc reverse descending connectivity array.
779  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
780  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
781  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
782  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
783  */
784 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
785                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
786 {
787   if(!desc || !descIndx || !revDesc || !revDescIndx)
788     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
789   const int *descPtr=desc->getConstPointer();
790   const int *descIPtr=descIndx->getConstPointer();
791   const int *revDescPtr=revDesc->getConstPointer();
792   const int *revDescIPtr=revDescIndx->getConstPointer();
793   //
794   int nbCells=descIndx->getNumberOfTuples()-1;
795   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
796   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
797   int *out1Ptr=out1->getPointer();
798   *out1Ptr++=0;
799   out0->reserve(desc->getNumberOfTuples());
800   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
801     {
802       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
803         {
804           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
805           s.erase(i);
806           out0->insertAtTheEnd(s.begin(),s.end());
807         }
808       *out1Ptr=out0->getNumberOfTuples();
809     }
810   neighbors=out0.retn();
811   neighborsIndx=out1.retn();
812 }
813
814 /// @cond INTERNAL
815
816 /*!
817  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
818  * For speed reasons no check of this will be done.
819  */
820 template<class SonsGenerator>
821 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
822 {
823   if(!desc || !descIndx || !revDesc || !revDescIndx)
824     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
825   checkConnectivityFullyDefined();
826   int nbOfCells=getNumberOfCells();
827   int nbOfNodes=getNumberOfNodes();
828   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
829   int *revNodalIndxPtr=revNodalIndx->getPointer();
830   const int *conn=_nodal_connec->getConstPointer();
831   const int *connIndex=_nodal_connec_index->getConstPointer();
832   std::string name="Mesh constituent of "; name+=getName();
833   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
834   ret->setCoords(getCoords());
835   ret->allocateCells(2*nbOfCells);
836   descIndx->alloc(nbOfCells+1,1);
837   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
838   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
839   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
840     {
841       int pos=connIndex[eltId];
842       int posP1=connIndex[eltId+1];
843       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
844       SonsGenerator sg(cm);
845       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
846       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
847       for(unsigned i=0;i<nbOfSons;i++)
848         {
849           INTERP_KERNEL::NormalizedCellType cmsId;
850           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
851           for(unsigned k=0;k<nbOfNodesSon;k++)
852             if(tmp[k]>=0)
853               revNodalIndxPtr[tmp[k]+1]++;
854           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
855           revDesc2->pushBackSilent(eltId);
856         }
857       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
858     }
859   int nbOfCellsM1=ret->getNumberOfCells();
860   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
861   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
862   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
863   int *revNodalPtr=revNodal->getPointer();
864   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
865   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
866   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
867     {
868       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
869       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
870       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
871         if(*iter>=0)//for polyhedrons
872           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
873     }
874   //
875   DataArrayInt *commonCells=0,*commonCellsI=0;
876   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
878   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
879   int newNbOfCellsM1=-1;
880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
881                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
882   std::vector<bool> isImpacted(nbOfCellsM1,false);
883   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
884     for(int work2=work[0];work2!=work[1];work2++)
885       isImpacted[commonCellsPtr[work2]]=true;
886   const int *o2nM1Ptr=o2nM1->getConstPointer();
887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
888   const int *n2oM1Ptr=n2oM1->getConstPointer();
889   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
890   ret2->copyTinyInfoFrom(this);
891   desc->alloc(descIndx->back(),1);
892   int *descPtr=desc->getPointer();
893   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
894   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
895     {
896       if(!isImpacted[i])
897         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
898       else
899         {
900           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
901             {
902               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
903               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
904             }
905           else
906             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
907         }
908     }
909   revDesc->reserve(newNbOfCellsM1);
910   revDescIndx->alloc(newNbOfCellsM1+1,1);
911   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
912   const int *revDesc2Ptr=revDesc2->getConstPointer();
913   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
914     {
915       int oldCellIdM1=n2oM1Ptr[i];
916       if(!isImpacted[oldCellIdM1])
917         {
918           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
919           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
920         }
921       else
922         {
923           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
924             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
925           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
926           commonCellsIPtr++;
927         }
928     }
929   //
930   return ret2.retn();
931 }
932
933 struct MEDCouplingAccVisit
934 {
935   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
936   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
937   int _new_nb_of_nodes;
938 };
939
940 /// @endcond
941
942 /*!
943  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
944  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
945  * array of cell ids. Pay attention that after conversion all algorithms work slower
946  * with \a this mesh than before conversion. <br> If an exception is thrown during the
947  * conversion due presence of invalid ids in the array of cells to convert, as a
948  * result \a this mesh contains some already converted elements. In this case the 2D
949  * mesh remains valid but 3D mesh becomes \b inconsistent!
950  *  \warning This method can significantly modify the order of geometric types in \a this,
951  *          hence, to write this mesh to the MED file, its cells must be sorted using
952  *          sortCellsInMEDFileFrmt().
953  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
954  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
955  *         cellIdsToConvertBg.
956  *  \throw If the coordinates array is not set.
957  *  \throw If the nodal connectivity of cells is node defined.
958  *  \throw If dimension of \a this mesh is not either 2 or 3.
959  *
960  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
961  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
962  */
963 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
964 {
965   checkFullyDefined();
966   int dim=getMeshDimension();
967   if(dim<2 || dim>3)
968     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
969   int nbOfCells=getNumberOfCells();
970   if(dim==2)
971     {
972       const int *connIndex=_nodal_connec_index->getConstPointer();
973       int *conn=_nodal_connec->getPointer();
974       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
975         {
976           if(*iter>=0 && *iter<nbOfCells)
977             {
978               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
979               if(!cm.isQuadratic())
980                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
981               else
982                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
983             }
984           else
985             {
986               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
987               oss << " in range [0," << nbOfCells << ") !";
988               throw INTERP_KERNEL::Exception(oss.str().c_str());
989             }
990         }
991     }
992   else
993     {
994       int *connIndex=_nodal_connec_index->getPointer();
995       int connIndexLgth=_nodal_connec_index->getNbOfElems();
996       const int *connOld=_nodal_connec->getConstPointer();
997       int connOldLgth=_nodal_connec->getNbOfElems();
998       std::vector<int> connNew(connOld,connOld+connOldLgth);
999       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1000         {
1001           if(*iter>=0 && *iter<nbOfCells)
1002             {
1003               int pos=connIndex[*iter];
1004               int posP1=connIndex[(*iter)+1];
1005               int lgthOld=posP1-pos-1;
1006               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1007               connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1008               unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1009               int *tmp=new int[nbOfFaces*lgthOld];
1010               int *work=tmp;
1011               for(int j=0;j<(int)nbOfFaces;j++)
1012                 {
1013                   INTERP_KERNEL::NormalizedCellType type;
1014                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1015                   work+=offset;
1016                   *work++=-1;
1017                 }
1018               std::size_t newLgth=std::distance(tmp,work)-1;
1019               std::size_t delta=newLgth-lgthOld;
1020               std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1021               connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1022               std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1023               delete [] tmp;
1024             }
1025           else
1026             {
1027               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1028               oss << " in range [0," << nbOfCells << ") !";
1029               throw INTERP_KERNEL::Exception(oss.str().c_str());
1030             }
1031         }
1032       _nodal_connec->alloc((int)connNew.size(),1);
1033       int *newConnPtr=_nodal_connec->getPointer();
1034       std::copy(connNew.begin(),connNew.end(),newConnPtr);
1035     }
1036   computeTypes();
1037 }
1038
1039 /*!
1040  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1041  * polyhedrons (if \a this is a 3D mesh).
1042  *  \warning As this method is purely for user-friendliness and no optimization is
1043  *          done to avoid construction of a useless vector, this method can be costly
1044  *          in memory.
1045  *  \throw If the coordinates array is not set.
1046  *  \throw If the nodal connectivity of cells is node defined.
1047  *  \throw If dimension of \a this mesh is not either 2 or 3.
1048  */
1049 void MEDCouplingUMesh::convertAllToPoly()
1050 {
1051   int nbOfCells=getNumberOfCells();
1052   std::vector<int> cellIds(nbOfCells);
1053   for(int i=0;i<nbOfCells;i++)
1054     cellIds[i]=i;
1055   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1056 }
1057
1058 /*!
1059  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1060  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1061  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1062  * base facet of the volume and the second half of nodes describes an opposite facet
1063  * having the same number of nodes as the base one. This method converts such
1064  * connectivity to a valid polyhedral format where connectivity of each facet is
1065  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1066  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1067  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1068  * a correct orientation of the first facet of a polyhedron, else orientation of a
1069  * corrected cell is reverse.<br>
1070  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1071  * it releases the user from boring description of polyhedra connectivity in the valid
1072  * format.
1073  *  \throw If \a this->getMeshDimension() != 3.
1074  *  \throw If \a this->getSpaceDimension() != 3.
1075  *  \throw If the nodal connectivity of cells is not defined.
1076  *  \throw If the coordinates array is not set.
1077  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1078  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1079  *
1080  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1081  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1082  */
1083 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1084 {
1085   checkFullyDefined();
1086   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1087     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1088   int nbOfCells=getNumberOfCells();
1089   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1090   newCi->alloc(nbOfCells+1,1);
1091   int *newci=newCi->getPointer();
1092   const int *ci=_nodal_connec_index->getConstPointer();
1093   const int *c=_nodal_connec->getConstPointer();
1094   newci[0]=0;
1095   for(int i=0;i<nbOfCells;i++)
1096     {
1097       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1098       if(type==INTERP_KERNEL::NORM_POLYHED)
1099         {
1100           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1101             {
1102               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1103               throw INTERP_KERNEL::Exception(oss.str().c_str());
1104             }
1105           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1106           if(n2%2!=0)
1107             {
1108               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron with 1 face but there is a mismatch of number of nodes in face should be even !";
1109               throw INTERP_KERNEL::Exception(oss.str().c_str());
1110             }
1111           int n1=(int)(n2/2);
1112           newci[i+1]=7*n1+2+newci[i];//6*n1 (nodal length) + n1+2 (number of faces) - 1 (number of '-1' separator is equal to number of faces -1) + 1 (for cell type)
1113         }
1114       else
1115         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1116     }
1117   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1118   newC->alloc(newci[nbOfCells],1);
1119   int *newc=newC->getPointer();
1120   for(int i=0;i<nbOfCells;i++)
1121     {
1122       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1123       if(type==INTERP_KERNEL::NORM_POLYHED)
1124         {
1125           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1126           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1127           *newc++=-1;
1128           for(std::size_t j=0;j<n1;j++)
1129             {
1130               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1131               newc[n1+5*j]=-1;
1132               newc[n1+5*j+1]=c[ci[i]+1+j];
1133               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1134               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1135               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1136             }
1137           newc+=n1*6;
1138         }
1139       else
1140         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1141     }
1142   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1143   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1144 }
1145
1146
1147 /*!
1148  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1149  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1150  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1151  *          to write this mesh to the MED file, its cells must be sorted using
1152  *          sortCellsInMEDFileFrmt().
1153  * \return \c true if at least one cell has been converted, \c false else. In the
1154  *         last case the nodal connectivity remains unchanged.
1155  * \throw If the coordinates array is not set.
1156  * \throw If the nodal connectivity of cells is not defined.
1157  * \throw If \a this->getMeshDimension() < 0.
1158  */
1159 bool MEDCouplingUMesh::unPolyze()
1160 {
1161   checkFullyDefined();
1162   int mdim=getMeshDimension();
1163   if(mdim<0)
1164     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1165   if(mdim<=1)
1166     return false;
1167   int nbOfCells=getNumberOfCells();
1168   if(nbOfCells<1)
1169     return false;
1170   int initMeshLgth=getMeshLength();
1171   int *conn=_nodal_connec->getPointer();
1172   int *index=_nodal_connec_index->getPointer();
1173   int posOfCurCell=0;
1174   int newPos=0;
1175   int lgthOfCurCell;
1176   bool ret=false;
1177   for(int i=0;i<nbOfCells;i++)
1178     {
1179       lgthOfCurCell=index[i+1]-posOfCurCell;
1180       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1181       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1182       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1183       int newLgth;
1184       if(cm.isDynamic())
1185         {
1186           switch(cm.getDimension())
1187             {
1188             case 2:
1189               {
1190                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1191                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1192                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1193                 break;
1194               }
1195             case 3:
1196               {
1197                 int nbOfFaces,lgthOfPolyhConn;
1198                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1199                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1200                 break;
1201               }
1202             case 1:
1203               {
1204                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1205                 break;
1206               }
1207             }
1208           ret=ret || (newType!=type);
1209           conn[newPos]=newType;
1210           newPos+=newLgth+1;
1211           posOfCurCell=index[i+1];
1212           index[i+1]=newPos;
1213         }
1214       else
1215         {
1216           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1217           newPos+=lgthOfCurCell;
1218           posOfCurCell+=lgthOfCurCell;
1219           index[i+1]=newPos;
1220         }
1221     }
1222   if(newPos!=initMeshLgth)
1223     _nodal_connec->reAlloc(newPos);
1224   if(ret)
1225     computeTypes();
1226   return ret;
1227 }
1228
1229 /*!
1230  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1231  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1232  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1233  *
1234  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not. This epsilon is used to recenter around origin to have maximal 
1235  *             precision.
1236  */
1237 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1238 {
1239   checkFullyDefined();
1240   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1241     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1242   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1243   coords->recenterForMaxPrecision(eps);
1244   //
1245   int nbOfCells=getNumberOfCells();
1246   const int *conn=_nodal_connec->getConstPointer();
1247   const int *index=_nodal_connec_index->getConstPointer();
1248   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1249   connINew->alloc(nbOfCells+1,1);
1250   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1251   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1252   bool changed=false;
1253   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1254     {
1255       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1256         {
1257           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1258           changed=true;
1259         }
1260       else
1261         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1262       *connINewPtr=connNew->getNumberOfTuples();
1263     }
1264   if(changed)
1265     setConnectivity(connNew,connINew,false);
1266 }
1267
1268 /*!
1269  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1270  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1271  * the format of returned DataArrayInt instance.
1272  * 
1273  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1274  * \sa MEDCouplingUMesh::getNodeIdsInUse
1275  */
1276 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1277 {
1278   checkConnectivityFullyDefined();
1279   int nbOfCells=getNumberOfCells();
1280   const int *connIndex=_nodal_connec_index->getConstPointer();
1281   const int *conn=_nodal_connec->getConstPointer();
1282   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1283   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1284   std::vector<bool> retS(maxElt,false);
1285   for(int i=0;i<nbOfCells;i++)
1286     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1287       if(conn[j]>=0)
1288         retS[conn[j]]=true;
1289   int sz=0;
1290   for(int i=0;i<maxElt;i++)
1291     if(retS[i])
1292       sz++;
1293   DataArrayInt *ret=DataArrayInt::New();
1294   ret->alloc(sz,1);
1295   int *retPtr=ret->getPointer();
1296   for(int i=0;i<maxElt;i++)
1297     if(retS[i])
1298       *retPtr++=i;
1299   return ret;
1300 }
1301
1302 /*!
1303  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1304  * \sa MEDCouplingUMesh::getNodeIdsInUse
1305  */
1306 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1307 {
1308   int nbOfNodes=(int)nodeIdsInUse.size();
1309   int nbOfCells=getNumberOfCells();
1310   const int *connIndex=_nodal_connec_index->getConstPointer();
1311   const int *conn=_nodal_connec->getConstPointer();
1312   for(int i=0;i<nbOfCells;i++)
1313     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1314       if(conn[j]>=0)
1315         {
1316           if(conn[j]<nbOfNodes)
1317             nodeIdsInUse[conn[j]]=true;
1318           else
1319             {
1320               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1321               throw INTERP_KERNEL::Exception(oss.str().c_str());
1322             }
1323         }
1324 }
1325
1326 /*!
1327  * Finds nodes not used in any cell and returns an array giving a new id to every node
1328  * by excluding the unused nodes, for which the array holds -1. The result array is
1329  * a mapping in "Old to New" mode. 
1330  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1331  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1332  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1333  *          if the node is unused or a new id else. The caller is to delete this
1334  *          array using decrRef() as it is no more needed.  
1335  *  \throw If the coordinates array is not set.
1336  *  \throw If the nodal connectivity of cells is not defined.
1337  *  \throw If the nodal connectivity includes an invalid id.
1338  *
1339  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1340  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1341  * \sa computeNodeIdsAlg()
1342  */
1343 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1344 {
1345   nbrOfNodesInUse=-1;
1346   int nbOfNodes=getNumberOfNodes();
1347   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1348   ret->alloc(nbOfNodes,1);
1349   int *traducer=ret->getPointer();
1350   std::fill(traducer,traducer+nbOfNodes,-1);
1351   int nbOfCells=getNumberOfCells();
1352   const int *connIndex=_nodal_connec_index->getConstPointer();
1353   const int *conn=_nodal_connec->getConstPointer();
1354   for(int i=0;i<nbOfCells;i++)
1355     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1356       if(conn[j]>=0)
1357         {
1358           if(conn[j]<nbOfNodes)
1359             traducer[conn[j]]=1;
1360           else
1361             {
1362               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1363               throw INTERP_KERNEL::Exception(oss.str().c_str());
1364             }
1365         }
1366   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1367   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1368   return ret.retn();
1369 }
1370
1371 /*!
1372  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1373  * For each cell in \b this the number of nodes constituting cell is computed.
1374  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1375  * So for pohyhedrons some nodes can be counted several times in the returned result.
1376  * 
1377  * \return a newly allocated array
1378  */
1379 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1380 {
1381   checkConnectivityFullyDefined();
1382   int nbOfCells=getNumberOfCells();
1383   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1384   ret->alloc(nbOfCells,1);
1385   int *retPtr=ret->getPointer();
1386   const int *conn=getNodalConnectivity()->getConstPointer();
1387   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1388   for(int i=0;i<nbOfCells;i++,retPtr++)
1389     {
1390       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1391         *retPtr=connI[i+1]-connI[i]-1;
1392       else
1393         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1394     }
1395   return ret.retn();
1396 }
1397
1398 /*!
1399  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1400  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1401  * 
1402  * \return a newly allocated array
1403  */
1404 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
1405 {
1406   checkConnectivityFullyDefined();
1407   int nbOfCells=getNumberOfCells();
1408   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1409   ret->alloc(nbOfCells,1);
1410   int *retPtr=ret->getPointer();
1411   const int *conn=getNodalConnectivity()->getConstPointer();
1412   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1413   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1414     {
1415       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1416       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1417     }
1418   return ret.retn();
1419 }
1420
1421 /*!
1422  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1423  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1424  * array mean that the corresponding old node is no more used. 
1425  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1426  *           this->getNumberOfNodes() before call of this method. The caller is to
1427  *           delete this array using decrRef() as it is no more needed. 
1428  *  \throw If the coordinates array is not set.
1429  *  \throw If the nodal connectivity of cells is not defined.
1430  *  \throw If the nodal connectivity includes an invalid id.
1431  *
1432  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1433  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1434  */
1435 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1436 {
1437   return MEDCouplingPointSet::zipCoordsTraducer();
1438 }
1439
1440 /*!
1441  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1442  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1443  */
1444 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1445 {
1446   switch(compType)
1447     {
1448     case 0:
1449       return AreCellsEqual0(conn,connI,cell1,cell2);
1450     case 1:
1451       return AreCellsEqual1(conn,connI,cell1,cell2);
1452     case 2:
1453       return AreCellsEqual2(conn,connI,cell1,cell2);
1454     case 3:
1455       return AreCellsEqual3(conn,connI,cell1,cell2);
1456     case 7:
1457       return AreCellsEqual7(conn,connI,cell1,cell2);
1458     }
1459   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1460 }
1461
1462 /*!
1463  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1464  */
1465 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1466 {
1467   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1468     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1469   return 0;
1470 }
1471
1472 /*!
1473  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1474  */
1475 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1476 {
1477   int sz=connI[cell1+1]-connI[cell1];
1478   if(sz==connI[cell2+1]-connI[cell2])
1479     {
1480       if(conn[connI[cell1]]==conn[connI[cell2]])
1481         {
1482           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1483           unsigned dim=cm.getDimension();
1484           if(dim!=3)
1485             {
1486               if(dim!=1)
1487                 {
1488                   int sz1=2*(sz-1);
1489                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1490                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1491                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1492                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1493                   return work!=tmp+sz1?1:0;
1494                 }
1495               else
1496                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1497             }
1498           else
1499             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1500         }
1501     }
1502   return 0;
1503 }
1504
1505 /*!
1506  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1507  */
1508 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1509 {
1510   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1511     {
1512       if(conn[connI[cell1]]==conn[connI[cell2]])
1513         {
1514           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1515           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1516           return s1==s2?1:0;
1517         }
1518     }
1519   return 0;
1520 }
1521
1522 /*!
1523  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1524  */
1525 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1526 {
1527   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1528     {
1529       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1530       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1531       return s1==s2?1:0;
1532     }
1533   return 0;
1534 }
1535
1536 /*!
1537  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1538  */
1539 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1540 {
1541   int sz=connI[cell1+1]-connI[cell1];
1542   if(sz==connI[cell2+1]-connI[cell2])
1543     {
1544       if(conn[connI[cell1]]==conn[connI[cell2]])
1545         {
1546           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1547           unsigned dim=cm.getDimension();
1548           if(dim!=3)
1549             {
1550               if(dim!=1)
1551                 {
1552                   int sz1=2*(sz-1);
1553                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1554                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1555                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1556                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1557                   if(work!=tmp+sz1)
1558                     return 1;
1559                   else
1560                     {
1561                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1562                       std::reverse_iterator<int *> it2((int *)tmp);
1563                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1564                         return 2;
1565                       else
1566                         return 0;
1567                     }
1568                   
1569                   return work!=tmp+sz1?1:0;
1570                 }
1571               else
1572                 {//case of SEG2 and SEG3
1573                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1574                     return 1;
1575                   if(!cm.isQuadratic())
1576                     {
1577                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1578                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1579                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1580                         return 2;
1581                       return 0;
1582                     }
1583                   else
1584                     {
1585                       if(conn[connI[cell1]+1]==conn[connI[cell2]+2] && conn[connI[cell1]+2]==conn[connI[cell2]+1] && conn[connI[cell1]+3]==conn[connI[cell2]+3])
1586                         return 2;
1587                       return 0;
1588                     }
1589                 }
1590             }
1591           else
1592             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1593         }
1594     }
1595   return 0;
1596 }
1597
1598 /*!
1599  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1600  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1601  * and result remains unchanged.
1602  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1603  * If in 'candidates' pool -1 value is considered as an empty value.
1604  * WARNING this method returns only ONE set of result !
1605  */
1606 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1607 {
1608   if(candidates.size()<1)
1609     return false;
1610   bool ret=false;
1611   std::vector<int>::const_iterator iter=candidates.begin();
1612   int start=(*iter++);
1613   for(;iter!=candidates.end();iter++)
1614     {
1615       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1616       if(status!=0)
1617         {
1618           if(!ret)
1619             {
1620               result->pushBackSilent(start);
1621               ret=true;
1622             }
1623           if(status==1)
1624             result->pushBackSilent(*iter);
1625           else
1626             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1627         }
1628     }
1629   return ret;
1630 }
1631
1632 /*!
1633  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1634  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1635  *
1636  * \param [in] compType input specifying the technique used to compare cells each other.
1637  *   - 0 : exactly. A cell is detected to be the same if and only if the connectivity is exactly the same without permutation and types same too. This is the strongest policy.
1638  *   - 1 : permutation same orientation. cell1 and cell2 are considered equal if the connectivity of cell2 can be deduced by those of cell1 by direct permutation (with exactly the same orientation)
1639  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1640  *   - 2 : nodal. cell1 and cell2 are equal if and only if cell1 and cell2 have same type and have the same nodes constituting connectivity. This is the laziest policy. This policy
1641  * can be used for users not sensitive to orientation of cell
1642  * \param [in] startCellId specifies the cellId starting from which the equality computation will be carried out. By default it is 0, which it means that all cells in \a this will be scanned.
1643  * \param [out] commonCells
1644  * \param [out] commonCellsI
1645  * \return the correspondance array old to new in a newly allocated array.
1646  * 
1647  */
1648 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1649 {
1650   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1651   getReverseNodalConnectivity(revNodal,revNodalI);
1652   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1653 }
1654
1655 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1656                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1657 {
1658   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1659   int nbOfCells=nodalI->getNumberOfTuples()-1;
1660   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1661   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1662   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1663   std::vector<bool> isFetched(nbOfCells,false);
1664   if(startCellId==0)
1665     {
1666       for(int i=0;i<nbOfCells;i++)
1667         {
1668           if(!isFetched[i])
1669             {
1670               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1671               std::vector<int> v,v2;
1672               if(connOfNode!=connPtr+connIPtr[i+1])
1673                 {
1674                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1675                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1676                   connOfNode++;
1677                 }
1678               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1679                 if(*connOfNode>=0)
1680                   {
1681                     v=v2;
1682                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1683                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1684                     v2.resize(std::distance(v2.begin(),it));
1685                   }
1686               if(v2.size()>1)
1687                 {
1688                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1689                     {
1690                       int pos=commonCellsI->back();
1691                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1692                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1693                         isFetched[*it]=true;
1694                     }
1695                 }
1696             }
1697         }
1698     }
1699   else
1700     {
1701       for(int i=startCellId;i<nbOfCells;i++)
1702         {
1703           if(!isFetched[i])
1704             {
1705               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1706               std::vector<int> v,v2;
1707               if(connOfNode!=connPtr+connIPtr[i+1])
1708                 {
1709                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1710                   connOfNode++;
1711                 }
1712               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1713                 if(*connOfNode>=0)
1714                   {
1715                     v=v2;
1716                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1717                     v2.resize(std::distance(v2.begin(),it));
1718                   }
1719               if(v2.size()>1)
1720                 {
1721                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1722                     {
1723                       int pos=commonCellsI->back();
1724                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1725                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1726                         isFetched[*it]=true;
1727                     }
1728                 }
1729             }
1730         }
1731     }
1732   commonCellsArr=commonCells.retn();
1733   commonCellsIArr=commonCellsI.retn();
1734 }
1735
1736 /*!
1737  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1738  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1739  * than \a other->getNumberOfCells() in the returned array means that there is no
1740  * corresponding cell in \a this mesh.
1741  * It is expected that \a this and \a other meshes share the same node coordinates
1742  * array, if it is not so an exception is thrown. 
1743  *  \param [in] other - the mesh to compare with.
1744  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1745  *         valid values [0,1,2], see zipConnectivityTraducer().
1746  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1747  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1748  *         values. The caller is to delete this array using
1749  *         decrRef() as it is no more needed.
1750  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1751  *         mesh.
1752  *
1753  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1754  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1755  *  \sa checkDeepEquivalOnSameNodesWith()
1756  *  \sa checkGeoEquivalWith()
1757  */
1758 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1759 {
1760   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1761   int nbOfCells=getNumberOfCells();
1762   static const int possibleCompType[]={0,1,2};
1763   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1764     {
1765       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1766       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1767       oss << " !";
1768       throw INTERP_KERNEL::Exception(oss.str().c_str());
1769     }
1770   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1771   arr=o2n->substr(nbOfCells);
1772   arr->setName(other->getName());
1773   int tmp;
1774   if(other->getNumberOfCells()==0)
1775     return true;
1776   return arr->getMaxValue(tmp)<nbOfCells;
1777 }
1778
1779 /*!
1780  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1781  * This method tries to determine if \b other is fully included in \b this.
1782  * The main difference is that this method is not expected to throw exception.
1783  * This method has two outputs :
1784  *
1785  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1786  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1787  */
1788 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1789 {
1790   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1791   DataArrayInt *commonCells=0,*commonCellsI=0;
1792   int thisNbCells=getNumberOfCells();
1793   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1794   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1795   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1796   int otherNbCells=other->getNumberOfCells();
1797   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1798   arr2->alloc(otherNbCells,1);
1799   arr2->fillWithZero();
1800   int *arr2Ptr=arr2->getPointer();
1801   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1802   for(int i=0;i<nbOfCommon;i++)
1803     {
1804       int start=commonCellsPtr[commonCellsIPtr[i]];
1805       if(start<thisNbCells)
1806         {
1807           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1808             {
1809               int sig=commonCellsPtr[j]>0?1:-1;
1810               int val=std::abs(commonCellsPtr[j])-1;
1811               if(val>=thisNbCells)
1812                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1813             }
1814         }
1815     }
1816   arr2->setName(other->getName());
1817   if(arr2->presenceOfValue(0))
1818     return false;
1819   arr=arr2.retn();
1820   return true;
1821 }
1822
1823 /*!
1824  * Merges nodes equal within \a precision and returns an array describing the 
1825  * permutation used to remove duplicate nodes.
1826  *  \param [in] precision - minimal absolute distance between two nodes at which they are
1827  *              considered not coincident.
1828  *  \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1829  *  \param [out] newNbOfNodes - number of nodes remaining after the removal.
1830  *  \return DataArrayInt * - the permutation array in "Old to New" mode. For more 
1831  *          info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1832  *          is to delete this array using decrRef() as it is no more needed.
1833  *  \throw If the coordinates array is not set.
1834  *  \throw If the nodal connectivity of cells is not defined.
1835  *
1836  *  \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1837  *  \ref  py_mcumesh_mergeNodes "Here is a Python example".
1838  */
1839 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1840 {
1841   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1842   if(areNodesMerged)
1843     renumberNodes(ret->begin(),newNbOfNodes);
1844   return ret.retn();
1845 }
1846
1847
1848 /*!
1849  * Merges nodes equal within \a precision and returns an array describing the 
1850  * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
1851  *  of merged nodes is changed to be at their barycenter.
1852  *  \param [in] precision - minimal absolute distance between two nodes at which they are
1853  *              considered not coincident.
1854  *  \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1855  *  \param [out] newNbOfNodes - number of nodes remaining after the removal.
1856  *  \return DataArrayInt * - the permutation array in "Old to New" mode. For more 
1857  *          info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1858  *          is to delete this array using decrRef() as it is no more needed.
1859  *  \throw If the coordinates array is not set.
1860  *  \throw If the nodal connectivity of cells is not defined.
1861  *
1862  *  \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1863  *  \ref  py_mcumesh_mergeNodes "Here is a Python example".
1864  */
1865 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
1866 {
1867   DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1868   if(areNodesMerged)
1869     renumberNodes2(ret->getConstPointer(),newNbOfNodes);
1870   return ret;
1871 }
1872
1873 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1874 {
1875   if(!other)
1876     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1877   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1878   if(!otherC)
1879     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1880   std::vector<const MEDCouplingUMesh *> ms(2);
1881   ms[0]=this;
1882   ms[1]=otherC;
1883   return MergeUMeshesOnSameCoords(ms);
1884 }
1885
1886 /*!
1887  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1888  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1889  * cellIds is not given explicitely but by a range python like.
1890  * 
1891  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
1892  * \return a newly allocated
1893  * 
1894  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1895  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1896  */
1897 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1898 {
1899   if(getMeshDimension()!=-1)
1900     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1901   else
1902     {
1903       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1904       if(newNbOfCells!=1)
1905         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1906       if(start!=0)
1907         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1908       incrRef();
1909       return const_cast<MEDCouplingUMesh *>(this);
1910     }
1911 }
1912
1913 /*!
1914  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1915  * The result mesh shares or not the node coordinates array with \a this mesh depending
1916  * on \a keepCoords parameter.
1917  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1918  *           to write this mesh to the MED file, its cells must be sorted using
1919  *           sortCellsInMEDFileFrmt().
1920  *  \param [in] begin - an array of cell ids to include to the new mesh.
1921  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1922  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1923  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1924  *         by calling zipCoords().
1925  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1926  *         to delete this mesh using decrRef() as it is no more needed. 
1927  *  \throw If the coordinates array is not set.
1928  *  \throw If the nodal connectivity of cells is not defined.
1929  *  \throw If any cell id in the array \a begin is not valid.
1930  *
1931  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1932  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1933  */
1934 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1935 {
1936   if(getMeshDimension()!=-1)
1937     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1938   else
1939     {
1940       if(end-begin!=1)
1941         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1942       if(begin[0]!=0)
1943         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1944       incrRef();
1945       return const_cast<MEDCouplingUMesh *>(this);
1946     }
1947 }
1948
1949 /*!
1950  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1951  *
1952  * This method allows to partially modify some cells in \b this (whose list is specified by [ \b cellIdsBg, \b cellIdsEnd ) ) with cells coming in \b otherOnSameCoordsThanThis.
1953  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1954  * The number of cells of \b this will remain the same with this method.
1955  *
1956  * \param [in] begin begin of cell ids (included) of cells in this to assign
1957  * \param [in] end end of cell ids (excluded) of cells in this to assign
1958  * \param [in] otherOnSameCoordsThanThis an another mesh with same meshdimension than \b this with exactly the same number of cells than cell ids list in [\b cellIdsBg, \b cellIdsEnd ).
1959  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1960  */
1961 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1962 {
1963   checkConnectivityFullyDefined();
1964   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1965   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1966     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1967   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1968     {
1969       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1970       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1971       throw INTERP_KERNEL::Exception(oss.str().c_str());
1972     }
1973   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1974   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1975     {
1976       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1977       throw INTERP_KERNEL::Exception(oss.str().c_str());
1978     }
1979   int nbOfCells=getNumberOfCells();
1980   bool easyAssign=true;
1981   const int *connI=_nodal_connec_index->getConstPointer();
1982   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1983   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1984     {
1985       if(*it>=0 && *it<nbOfCells)
1986         {
1987           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1988         }
1989       else
1990         {
1991           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1992           throw INTERP_KERNEL::Exception(oss.str().c_str());
1993         }
1994     }
1995   if(easyAssign)
1996     {
1997       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1998       computeTypes();
1999     }
2000   else
2001     {
2002       DataArrayInt *arrOut=0,*arrIOut=0;
2003       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2004                                                arrOut,arrIOut);
2005       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2006       setConnectivity(arrOut,arrIOut,true);
2007     }
2008 }
2009
2010 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2011 {
2012   checkConnectivityFullyDefined();
2013   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2014   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2015     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2016   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2017     {
2018       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2019       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2020       throw INTERP_KERNEL::Exception(oss.str().c_str());
2021     }
2022   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2023   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2024     {
2025       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2026       throw INTERP_KERNEL::Exception(oss.str().c_str());
2027     }
2028   int nbOfCells=getNumberOfCells();
2029   bool easyAssign=true;
2030   const int *connI=_nodal_connec_index->getConstPointer();
2031   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2032   int it=start;
2033   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2034     {
2035       if(it>=0 && it<nbOfCells)
2036         {
2037           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2038         }
2039       else
2040         {
2041           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2042           throw INTERP_KERNEL::Exception(oss.str().c_str());
2043         }
2044     }
2045   if(easyAssign)
2046     {
2047       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2048       computeTypes();
2049     }
2050   else
2051     {
2052       DataArrayInt *arrOut=0,*arrIOut=0;
2053       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2054                                                 arrOut,arrIOut);
2055       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2056       setConnectivity(arrOut,arrIOut,true);
2057     }
2058 }                      
2059
2060 /*!
2061  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2062  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2063  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2064  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2065  *
2066  * \param [in] begin input start of array of node ids.
2067  * \param [in] end input end of array of node ids.
2068  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2069  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2070  */
2071 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2072 {
2073   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2074   checkConnectivityFullyDefined();
2075   int tmp=-1;
2076   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2077   std::vector<bool> fastFinder(sz,false);
2078   for(const int *work=begin;work!=end;work++)
2079     if(*work>=0 && *work<sz)
2080       fastFinder[*work]=true;
2081   int nbOfCells=getNumberOfCells();
2082   const int *conn=getNodalConnectivity()->getConstPointer();
2083   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2084   for(int i=0;i<nbOfCells;i++)
2085     {
2086       int ref=0,nbOfHit=0;
2087       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2088         if(*work2>=0)
2089           {
2090             ref++;
2091             if(fastFinder[*work2])
2092               nbOfHit++;
2093           }
2094       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2095         cellIdsKept->pushBackSilent(i);
2096     }
2097   cellIdsKeptArr=cellIdsKept.retn();
2098 }
2099
2100 /*!
2101  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2102  * this->getMeshDimension(), that bound some cells of \a this mesh.
2103  * The cells of lower dimension to include to the result mesh are selected basing on
2104  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2105  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2106  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2107  * created mesh shares the node coordinates array with \a this mesh. 
2108  *  \param [in] begin - the array of node ids.
2109  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2110  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2111  *         array \a begin are added, else cells whose any node is in the
2112  *         array \a begin are added.
2113  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2114  *         to delete this mesh using decrRef() as it is no more needed. 
2115  *  \throw If the coordinates array is not set.
2116  *  \throw If the nodal connectivity of cells is not defined.
2117  *  \throw If any node id in \a begin is not valid.
2118  *
2119  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2120  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2121  */
2122 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2123 {
2124   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2125   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2126   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2127   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2128   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2129 }
2130
2131 /*!
2132  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2133  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2134  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2135  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2136  *         by calling zipCoords().
2137  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2138  *         to delete this mesh using decrRef() as it is no more needed. 
2139  *  \throw If the coordinates array is not set.
2140  *  \throw If the nodal connectivity of cells is not defined.
2141  *
2142  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2143  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2144  */
2145 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2146 {
2147   DataArrayInt *desc=DataArrayInt::New();
2148   DataArrayInt *descIndx=DataArrayInt::New();
2149   DataArrayInt *revDesc=DataArrayInt::New();
2150   DataArrayInt *revDescIndx=DataArrayInt::New();
2151   //
2152   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2153   revDesc->decrRef();
2154   desc->decrRef();
2155   descIndx->decrRef();
2156   int nbOfCells=meshDM1->getNumberOfCells();
2157   const int *revDescIndxC=revDescIndx->getConstPointer();
2158   std::vector<int> boundaryCells;
2159   for(int i=0;i<nbOfCells;i++)
2160     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2161       boundaryCells.push_back(i);
2162   revDescIndx->decrRef();
2163   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2164   return ret;
2165 }
2166
2167 /*!
2168  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2169  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2170  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2171  */
2172 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2173 {
2174   checkFullyDefined();
2175   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2176   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2177   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2178   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2179   //
2180   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2181   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2182   //
2183   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2184   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2185   const int *revDescPtr=revDesc->getConstPointer();
2186   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2187   int nbOfCells=getNumberOfCells();
2188   std::vector<bool> ret1(nbOfCells,false);
2189   int sz=0;
2190   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2191     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2192       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2193   //
2194   DataArrayInt *ret2=DataArrayInt::New();
2195   ret2->alloc(sz,1);
2196   int *ret2Ptr=ret2->getPointer();
2197   sz=0;
2198   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2199     if(*it)
2200       *ret2Ptr++=sz;
2201   ret2->setName("BoundaryCells");
2202   return ret2;
2203 }
2204
2205 /*!
2206  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2207  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2208  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2209  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2210  *
2211  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2212  * This method method returns cells ids set s = s1 + s2 where :
2213  * 
2214  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2215  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2216  *
2217  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2218  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2219  *
2220  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2221  * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2222  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2223  */
2224 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2225 {
2226   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2227     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2228   checkConnectivityFullyDefined();
2229   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2230   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2231     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2232   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2233   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2234   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2235   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2236   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2237   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2238   DataArrayInt *idsOtherInConsti=0;
2239   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2240   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2241   if(!b)
2242     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2243   std::set<int> s1;
2244   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2245     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2246   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2247   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2248   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2249   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2250   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2251   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2252   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2253   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2254   neighThisPartAuto=0;
2255   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2256   const int li[2]={0,1};
2257   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2258   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2259   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2260   s_renum1->sort();
2261   //
2262   cellIdsRk0=s0arr.retn();
2263   cellIdsRk1=s_renum1.retn();
2264 }
2265
2266 /*!
2267  * This method computes the skin of \b this. That is to say the consituting meshdim-1 mesh is built and only the boundary subpart is
2268  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2269  * 
2270  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2271  */
2272 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2273 {
2274   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2275   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2276   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2278   //
2279   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2280   revDesc=0; desc=0; descIndx=0;
2281   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2282   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2283   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2284 }
2285
2286 /*!
2287  * Finds nodes lying on the boundary of \a this mesh.
2288  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2289  *          nodes. The caller is to delete this array using decrRef() as it is no
2290  *          more needed.
2291  *  \throw If the coordinates array is not set.
2292  *  \throw If the nodal connectivity of cells is node defined.
2293  *
2294  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2295  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2296  */
2297 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2298 {
2299   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2300   return skin->computeFetchedNodeIds();
2301 }
2302
2303 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2304 {
2305   incrRef();
2306   return const_cast<MEDCouplingUMesh *>(this);
2307 }
2308
2309 /*!
2310  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2311  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2312  * This method searches for nodes needed to be duplicated. These nodes are nodes fetched by \b otherDimM1OnSameCoords which are not part of the boundary of \b otherDimM1OnSameCoords.
2313  * If a node is in the boundary of \b this \b and in the boundary of \b otherDimM1OnSameCoords this node is considerd as needed to be duplicated.
2314  * When the set of node ids \b nodeIdsToDuplicate is computed, cell ids in \b this is searched so that their connectivity includes at least 1 node in \b nodeIdsToDuplicate.
2315  *
2316  * \param [in] otherDimM1OnSameCoords a mesh lying on the same coords than \b this and with a mesh dimension equal to those of \b this minus 1. WARNING this input
2317  *             parameter is altered during the call.
2318  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2319  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2320  * \param [out] cellIdsNotModified cell ids int \b this that lies on \b otherDimM1OnSameCoords mesh whose connectivity do \b not need to be modified as it is the case for \b cellIdsNeededToBeRenum.
2321  *
2322  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2323  */
2324 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2325                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2326 {
2327   checkFullyDefined();
2328   otherDimM1OnSameCoords.checkFullyDefined();
2329   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2330     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2331   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2332     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2333   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2334   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2337   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2338   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2339   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2340   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2341   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2342   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2343   //
2344   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2345   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2346   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2347   DataArrayInt *idsTmp=0;
2348   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2349   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2350   if(!b)
2351     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2352   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2353   DataArrayInt *tmp0=0,*tmp1=0;
2354   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2355   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2356   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2357   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2358   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2359   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2360   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2361   //
2362   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2363   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2364   nodeIdsToDuplicate=s3.retn();
2365 }
2366
2367 /*!
2368  * This method operates a modification of the connectivity and coords in \b this.
2369  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2370  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2371  * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2372  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2373  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2374  * 
2375  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2376  * 
2377  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2378  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2379  */
2380 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2381 {
2382   int nbOfNodes=getNumberOfNodes();
2383   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2384   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2385 }
2386
2387 /*!
2388  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2389  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2390  * This method is a generalization of shiftNodeNumbersInConn().
2391  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2392  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2393  *         this->getNumberOfNodes(), in "Old to New" mode. 
2394  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2395  *  \throw If the nodal connectivity of cells is not defined.
2396  *
2397  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2398  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2399  */
2400 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2401 {
2402   checkConnectivityFullyDefined();
2403   int *conn=getNodalConnectivity()->getPointer();
2404   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2405   int nbOfCells=getNumberOfCells();
2406   for(int i=0;i<nbOfCells;i++)
2407     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2408       {
2409         int& node=conn[iconn];
2410         if(node>=0)//avoid polyhedron separator
2411           {
2412             node=newNodeNumbersO2N[node];
2413           }
2414       }
2415   _nodal_connec->declareAsNew();
2416   updateTime();
2417 }
2418
2419 /*!
2420  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2421  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2422  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2423  * 
2424  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2425  */
2426 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2427 {
2428   checkConnectivityFullyDefined();
2429   int *conn=getNodalConnectivity()->getPointer();
2430   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2431   int nbOfCells=getNumberOfCells();
2432   for(int i=0;i<nbOfCells;i++)
2433     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2434       {
2435         int& node=conn[iconn];
2436         if(node>=0)//avoid polyhedron separator
2437           {
2438             node+=delta;
2439           }
2440       }
2441   _nodal_connec->declareAsNew();
2442   updateTime();
2443 }
2444
2445 /*!
2446  * This method operates a modification of the connectivity in \b this.
2447  * Coordinates are \b NOT considered here and will remain unchanged by this method. this->_coords can ever been null for the needs of this method.
2448  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2449  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2450  * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2451  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2452  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2453  * 
2454  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2455  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2456  * 
2457  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2458  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2459  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2460  */
2461 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2462 {
2463   checkConnectivityFullyDefined();
2464   std::map<int,int> m;
2465   int val=offset;
2466   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2467     m[*work]=val;
2468   int *conn=getNodalConnectivity()->getPointer();
2469   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2470   int nbOfCells=getNumberOfCells();
2471   for(int i=0;i<nbOfCells;i++)
2472     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2473       {
2474         int& node=conn[iconn];
2475         if(node>=0)//avoid polyhedron separator
2476           {
2477             std::map<int,int>::iterator it=m.find(node);
2478             if(it!=m.end())
2479               node=(*it).second;
2480           }
2481       }
2482   updateTime();
2483 }
2484
2485 /*!
2486  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2487  *
2488  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2489  * After the call of this method the number of cells remains the same as before.
2490  *
2491  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2492  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2493  * be strictly in [0;this->getNumberOfCells()).
2494  *
2495  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2496  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2497  * should be contained in[0;this->getNumberOfCells()).
2498  * 
2499  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2500  */
2501 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2502 {
2503   checkConnectivityFullyDefined();
2504   int nbCells=getNumberOfCells();
2505   const int *array=old2NewBg;
2506   if(check)
2507     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2508   //
2509   const int *conn=_nodal_connec->getConstPointer();
2510   const int *connI=_nodal_connec_index->getConstPointer();
2511   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2512   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2513   const int *n2oPtr=n2o->begin();
2514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2515   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2516   newConn->copyStringInfoFrom(*_nodal_connec);
2517   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2518   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2519   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2520   //
2521   int *newC=newConn->getPointer();
2522   int *newCI=newConnI->getPointer();
2523   int loc=0;
2524   newCI[0]=loc;
2525   for(int i=0;i<nbCells;i++)
2526     {
2527       int pos=n2oPtr[i];
2528       int nbOfElts=connI[pos+1]-connI[pos];
2529       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2530       loc+=nbOfElts;
2531       newCI[i+1]=loc;
2532     }
2533   //
2534   setConnectivity(newConn,newConnI);
2535   if(check)
2536     free(const_cast<int *>(array));
2537 }
2538
2539 /*!
2540  * Finds cells whose bounding boxes intersect a given bounding box.
2541  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2542  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2543  *         zMax (if in 3D). 
2544  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2545  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2546  *         extent of the bounding box of cell to produce an addition to this bounding box.
2547  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2548  *         cells. The caller is to delete this array using decrRef() as it is no more
2549  *         needed. 
2550  *  \throw If the coordinates array is not set.
2551  *  \throw If the nodal connectivity of cells is not defined.
2552  *
2553  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2554  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2555  */
2556 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2557 {
2558   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2559   if(getMeshDimension()==-1)
2560     {
2561       elems->pushBackSilent(0);
2562       return elems.retn();
2563     }
2564   int dim=getSpaceDimension();
2565   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2566   const int* conn      = getNodalConnectivity()->getConstPointer();
2567   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2568   const double* coords = getCoords()->getConstPointer();
2569   int nbOfCells=getNumberOfCells();
2570   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2571     {
2572       for (int i=0; i<dim; i++)
2573         {
2574           elem_bb[i*2]=std::numeric_limits<double>::max();
2575           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2576         }
2577
2578       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2579         {
2580           int node= conn[inode];
2581           if(node>=0)//avoid polyhedron separator
2582             {
2583               for (int idim=0; idim<dim; idim++)
2584                 {
2585                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2586                     {
2587                       elem_bb[idim*2] = coords[node*dim+idim] ;
2588                     }
2589                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2590                     {
2591                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2592                     }
2593                 }
2594             }
2595         }
2596       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2597         elems->pushBackSilent(ielem);
2598     }
2599   return elems.retn();
2600 }
2601
2602 /*!
2603  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2604  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2605  * added in 'elems' parameter.
2606  */
2607 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2608 {
2609   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2610   if(getMeshDimension()==-1)
2611     {
2612       elems->pushBackSilent(0);
2613       return elems.retn();
2614     }
2615   int dim=getSpaceDimension();
2616   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2617   const int* conn      = getNodalConnectivity()->getConstPointer();
2618   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2619   const double* coords = getCoords()->getConstPointer();
2620   int nbOfCells=getNumberOfCells();
2621   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2622     {
2623       for (int i=0; i<dim; i++)
2624         {
2625           elem_bb[i*2]=std::numeric_limits<double>::max();
2626           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2627         }
2628
2629       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2630         {
2631           int node= conn[inode];
2632           if(node>=0)//avoid polyhedron separator
2633             {
2634               for (int idim=0; idim<dim; idim++)
2635                 {
2636                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2637                     {
2638                       elem_bb[idim*2] = coords[node*dim+idim] ;
2639                     }
2640                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2641                     {
2642                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2643                     }
2644                 }
2645             }
2646         }
2647       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2648         elems->pushBackSilent(ielem);
2649     }
2650   return elems.retn();
2651 }
2652
2653 /*!
2654  * Returns a type of a cell by its id.
2655  *  \param [in] cellId - the id of the cell of interest.
2656  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2657  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2658  */
2659 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2660 {
2661   const int *ptI=_nodal_connec_index->getConstPointer();
2662   const int *pt=_nodal_connec->getConstPointer();
2663   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2664     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2665   else
2666     {
2667       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2668       throw INTERP_KERNEL::Exception(oss.str().c_str());
2669     }
2670 }
2671
2672 /*!
2673  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2674  * This method does not throw exception if geometric type \a type is not in \a this.
2675  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2676  * The coordinates array is not considered here.
2677  *
2678  * \param [in] type the geometric type
2679  * \return cell ids in this having geometric type \a type.
2680  */
2681 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2682 {
2683   
2684   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2685   ret->alloc(0,1);
2686   checkConnectivityFullyDefined();
2687   int nbCells=getNumberOfCells();
2688   int mdim=getMeshDimension();
2689   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2690   if(mdim!=(int)cm.getDimension())
2691     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2692   const int *ptI=_nodal_connec_index->getConstPointer();
2693   const int *pt=_nodal_connec->getConstPointer();
2694   for(int i=0;i<nbCells;i++)
2695     {
2696       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2697         ret->pushBackSilent(i);
2698     }
2699   return ret.retn();
2700 }
2701
2702 /*!
2703  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2704  */
2705 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2706 {
2707   const int *ptI=_nodal_connec_index->getConstPointer();
2708   const int *pt=_nodal_connec->getConstPointer();
2709   int nbOfCells=getNumberOfCells();
2710   int ret=0;
2711   for(int i=0;i<nbOfCells;i++)
2712     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2713       ret++;
2714   return ret;
2715 }
2716
2717 /*!
2718  * Returns the nodal connectivity of a given cell.
2719  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2720  * all returned node ids can be used in getCoordinatesOfNode().
2721  *  \param [in] cellId - an id of the cell of interest.
2722  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2723  *         cleared before the appending.
2724  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2725  */
2726 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2727 {
2728   const int *ptI=_nodal_connec_index->getConstPointer();
2729   const int *pt=_nodal_connec->getConstPointer();
2730   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2731     if(*w>=0)
2732       conn.push_back(*w);
2733 }
2734
2735 std::string MEDCouplingUMesh::simpleRepr() const
2736 {
2737   static const char msg0[]="No coordinates specified !";
2738   std::ostringstream ret;
2739   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2740   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2741   int tmpp1,tmpp2;
2742   double tt=getTime(tmpp1,tmpp2);
2743   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2744   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2745   if(_mesh_dim>=-1)
2746     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2747   else
2748     { ret << " Mesh dimension has not been set or is invalid !"; }
2749   if(_coords!=0)
2750     {
2751       const int spaceDim=getSpaceDimension();
2752       ret << spaceDim << "\nInfo attached on space dimension : ";
2753       for(int i=0;i<spaceDim;i++)
2754         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2755       ret << "\n";
2756     }
2757   else
2758     ret << msg0 << "\n";
2759   ret << "Number of nodes : ";
2760   if(_coords!=0)
2761     ret << getNumberOfNodes() << "\n";
2762   else
2763     ret << msg0 << "\n";
2764   ret << "Number of cells : ";
2765   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2766     ret << getNumberOfCells() << "\n";
2767   else
2768     ret << "No connectivity specified !" << "\n";
2769   ret << "Cell types present : ";
2770   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2771     {
2772       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2773       ret << cm.getRepr() << " ";
2774     }
2775   ret << "\n";
2776   return ret.str();
2777 }
2778
2779 std::string MEDCouplingUMesh::advancedRepr() const
2780 {
2781   std::ostringstream ret;
2782   ret << simpleRepr();
2783   ret << "\nCoordinates array : \n___________________\n\n";
2784   if(_coords)
2785     _coords->reprWithoutNameStream(ret);
2786   else
2787     ret << "No array set !\n";
2788   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2789   reprConnectivityOfThisLL(ret);
2790   return ret.str();
2791 }
2792
2793 /*!
2794  * This method returns a C++ code that is a dump of \a this.
2795  * This method will throw if this is not fully defined.
2796  */
2797 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2798 {
2799   static const char coordsName[]="coords";
2800   static const char connName[]="conn";
2801   static const char connIName[]="connI";
2802   checkFullyDefined();
2803   std::ostringstream ret; ret << "// coordinates" << std::endl;
2804   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2805   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2806   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2807   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2808   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2809   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2810   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2811   return ret.str();
2812 }
2813
2814 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2815 {
2816   std::ostringstream ret;
2817   reprConnectivityOfThisLL(ret);
2818   return ret.str();
2819 }
2820
2821 /*!
2822  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2823  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2824  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2825  * some algos).
2826  * 
2827  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2828  * This method analyzes the 3 arrays of \a this. For each the following behaviour is done : if the array is null a newly one is created
2829  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2830  */
2831 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2832 {
2833   int mdim=getMeshDimension();
2834   if(mdim<0)
2835     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2836   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2837   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2838   bool needToCpyCT=true;
2839   if(!_nodal_connec)
2840     {
2841       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2842       needToCpyCT=false;
2843     }
2844   else
2845     {
2846       tmp1=_nodal_connec;
2847       tmp1->incrRef();
2848     }
2849   if(!_nodal_connec_index)
2850     {
2851       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2852       needToCpyCT=false;
2853     }
2854   else
2855     {
2856       tmp2=_nodal_connec_index;
2857       tmp2->incrRef();
2858     }
2859   ret->setConnectivity(tmp1,tmp2,false);
2860   if(needToCpyCT)
2861     ret->_types=_types;
2862   if(!_coords)
2863     {
2864       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2865       ret->setCoords(coords);
2866     }
2867   else
2868     ret->setCoords(_coords);
2869   return ret.retn();
2870 }
2871
2872 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2873 {
2874   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2875     {
2876       int nbOfCells=getNumberOfCells();
2877       const int *c=_nodal_connec->getConstPointer();
2878       const int *ci=_nodal_connec_index->getConstPointer();
2879       for(int i=0;i<nbOfCells;i++)
2880         {
2881           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2882           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2883           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2884           stream << "\n";
2885         }
2886     }
2887   else
2888     stream << "Connectivity not defined !\n";
2889 }
2890
2891 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2892 {
2893   const int *ptI=_nodal_connec_index->getConstPointer();
2894   const int *pt=_nodal_connec->getConstPointer();
2895   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2896     return ptI[cellId+1]-ptI[cellId]-1;
2897   else
2898     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2899 }
2900
2901 /*!
2902  * Returns types of cells of the specified part of \a this mesh.
2903  * This method avoids computing sub-mesh explicitely to get its types.
2904  *  \param [in] begin - an array of cell ids of interest.
2905  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2906  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2907  *         describing the cell types. 
2908  *  \throw If the coordinates array is not set.
2909  *  \throw If the nodal connectivity of cells is not defined.
2910  *  \sa getAllTypes()
2911  */
2912 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2913 {
2914   checkFullyDefined();
2915   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2916   const int *conn=_nodal_connec->getConstPointer();
2917   const int *connIndex=_nodal_connec_index->getConstPointer();
2918   for(const int *w=begin;w!=end;w++)
2919     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2920   return ret;
2921 }
2922
2923 /*!
2924  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2925  * a set of types of cells constituting \a this mesh. 
2926  * This method is for advanced users having prepared their connectivity before. For
2927  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2928  *  \param [in] conn - the nodal connectivity array. 
2929  *  \param [in] connIndex - the nodal connectivity index array.
2930  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2931  *         mesh is updated.
2932  */
2933 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2934 {
2935   DataArrayInt::SetArrayIn(conn,_nodal_connec);
2936   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2937   if(isComputingTypes)
2938     computeTypes();
2939   declareAsNew();
2940 }
2941
2942 /*!
2943  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2944  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2945  */
2946 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2947                                                                                  _nodal_connec(0),_nodal_connec_index(0),
2948                                                                                 _types(other._types)
2949 {
2950   if(other._nodal_connec)
2951     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2952   if(other._nodal_connec_index)
2953     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2954 }
2955
2956 MEDCouplingUMesh::~MEDCouplingUMesh()
2957 {
2958   if(_nodal_connec)
2959     _nodal_connec->decrRef();
2960   if(_nodal_connec_index)
2961     _nodal_connec_index->decrRef();
2962 }
2963
2964 /*!
2965  * Recomputes a set of cell types of \a this mesh. For more info see
2966  * \ref MEDCouplingUMeshNodalConnectivity.
2967  */
2968 void MEDCouplingUMesh::computeTypes()
2969 {
2970   if(_nodal_connec && _nodal_connec_index)
2971     {
2972       _types.clear();
2973       const int *conn=_nodal_connec->getConstPointer();
2974       const int *connIndex=_nodal_connec_index->getConstPointer();
2975       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2976       if (nbOfElem > 0)
2977         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2978           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2979     }
2980 }
2981
2982 /*!
2983  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2984  */
2985 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2986 {
2987   if(!_nodal_connec_index || !_nodal_connec || !_coords)
2988     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2989 }
2990
2991 /*!
2992  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2993  */
2994 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2995 {
2996   if(!_nodal_connec_index || !_nodal_connec)
2997     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2998 }
2999
3000 /*!
3001  * Returns a number of cells constituting \a this mesh. 
3002  *  \return int - the number of cells in \a this mesh.
3003  *  \throw If the nodal connectivity of cells is not defined.
3004  */
3005 int MEDCouplingUMesh::getNumberOfCells() const
3006
3007   if(_nodal_connec_index)
3008     return _nodal_connec_index->getNumberOfTuples()-1;
3009   else
3010     if(_mesh_dim==-1)
3011       return 1;
3012     else
3013       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3014 }
3015
3016 /*!
3017  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3018  * mesh. For more info see \ref MEDCouplingMeshesPage.
3019  *  \return int - the dimension of \a this mesh.
3020  *  \throw If the mesh dimension is not defined using setMeshDimension().
3021  */
3022 int MEDCouplingUMesh::getMeshDimension() const
3023 {
3024   if(_mesh_dim<-1)
3025     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3026   return _mesh_dim;
3027 }
3028
3029 /*!
3030  * Returns a length of the nodal connectivity array.
3031  * This method is for test reason. Normally the integer returned is not useable by
3032  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3033  *  \return int - the length of the nodal connectivity array.
3034  */
3035 int MEDCouplingUMesh::getMeshLength() const
3036 {
3037   return _nodal_connec->getNbOfElems();
3038 }
3039
3040 /*!
3041  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3042  */
3043 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3044 {
3045   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3046   tinyInfo.push_back(getMeshDimension());
3047   tinyInfo.push_back(getNumberOfCells());
3048   if(_nodal_connec)
3049     tinyInfo.push_back(getMeshLength());
3050   else
3051     tinyInfo.push_back(-1);
3052 }
3053
3054 /*!
3055  * First step of unserialization process.
3056  */
3057 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3058 {
3059   return tinyInfo[6]<=0;
3060 }
3061
3062 /*!
3063  * Second step of serialization process.
3064  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3065  */
3066 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3067 {
3068   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3069   if(tinyInfo[5]!=-1)
3070     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3071 }
3072
3073 /*!
3074  * Third and final step of serialization process.
3075  */
3076 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3077 {
3078   MEDCouplingPointSet::serialize(a1,a2);
3079   if(getMeshDimension()>-1)
3080     {
3081       a1=DataArrayInt::New();
3082       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3083       int *ptA1=a1->getPointer();
3084       const int *conn=getNodalConnectivity()->getConstPointer();
3085       const int *index=getNodalConnectivityIndex()->getConstPointer();
3086       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3087       std::copy(conn,conn+getMeshLength(),ptA1);
3088     }
3089   else
3090     a1=0;
3091 }
3092
3093 /*!
3094  * Second and final unserialization process.
3095  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3096  */
3097 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3098 {
3099   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3100   setMeshDimension(tinyInfo[5]);
3101   if(tinyInfo[7]!=-1)
3102     {
3103       // Connectivity
3104       const int *recvBuffer=a1->getConstPointer();
3105       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3106       myConnecIndex->alloc(tinyInfo[6]+1,1);
3107       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3108       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3109       myConnec->alloc(tinyInfo[7],1);
3110       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3111       setConnectivity(myConnec, myConnecIndex);
3112     }
3113 }
3114
3115 /*!
3116  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3117  * CellIds are given using range specified by a start an end and step.
3118  */
3119 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3120 {
3121   checkFullyDefined();
3122   int ncell=getNumberOfCells();
3123   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3124   ret->_mesh_dim=_mesh_dim;
3125   ret->setCoords(_coords);
3126   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3127   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3128   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3129   int work=start;
3130   const int *conn=_nodal_connec->getConstPointer();
3131   const int *connIndex=_nodal_connec_index->getConstPointer();
3132   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3133     {
3134       if(work>=0 && work<ncell)
3135         {
3136           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3137         }
3138       else
3139         {
3140           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3141           throw INTERP_KERNEL::Exception(oss.str().c_str());
3142         }
3143     }
3144   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3145   int *newConnPtr=newConn->getPointer();
3146   std::set<INTERP_KERNEL::NormalizedCellType> types;
3147   work=start;
3148   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3149     {
3150       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3151       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3152     }
3153   ret->setConnectivity(newConn,newConnI,false);
3154   ret->_types=types;
3155   ret->copyTinyInfoFrom(this);
3156   return ret.retn();
3157 }
3158
3159 /*!
3160  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3161  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3162  * The return newly allocated mesh will share the same coordinates as \a this.
3163  */
3164 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3165 {
3166   checkFullyDefined();
3167   int ncell=getNumberOfCells();
3168   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3169   ret->_mesh_dim=_mesh_dim;
3170   ret->setCoords(_coords);
3171   std::size_t nbOfElemsRet=std::distance(begin,end);
3172   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3173   connIndexRet[0]=0;
3174   const int *conn=_nodal_connec->getConstPointer();
3175   const int *connIndex=_nodal_connec_index->getConstPointer();
3176   int newNbring=0;
3177   for(const int *work=begin;work!=end;work++,newNbring++)
3178     {
3179       if(*work>=0 && *work<ncell)
3180         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3181       else
3182         {
3183           free(connIndexRet);
3184           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3185           throw INTERP_KERNEL::Exception(oss.str().c_str());
3186         }
3187     }
3188   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3189   int *connRetWork=connRet;
3190   std::set<INTERP_KERNEL::NormalizedCellType> types;
3191   for(const int *work=begin;work!=end;work++)
3192     {
3193       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3194       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3195     }
3196   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3197   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3198   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3199   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3200   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3201   ret->_types=types;
3202   ret->copyTinyInfoFrom(this);
3203   return ret.retn();
3204 }
3205
3206 /*!
3207  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3208  * mesh.<br>
3209  * For 1D cells, the returned field contains lengths.<br>
3210  * For 2D cells, the returned field contains areas.<br>
3211  * For 3D cells, the returned field contains volumes.
3212  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3213  *         orientation, i.e. the volume is always positive.
3214  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3215  *         and one time . The caller is to delete this field using decrRef() as it is no
3216  *         more needed.
3217  */
3218 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3219 {
3220   std::string name="MeasureOfMesh_";
3221   name+=getName();
3222   int nbelem=getNumberOfCells();
3223   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3224   field->setName(name.c_str());
3225   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3226   array->alloc(nbelem,1);
3227   double *area_vol=array->getPointer();
3228   field->setArray(array) ; array=0;
3229   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3230   field->synchronizeTimeWithMesh();
3231   if(getMeshDimension()!=-1)
3232     {
3233       int ipt;
3234       INTERP_KERNEL::NormalizedCellType type;
3235       int dim_space=getSpaceDimension();
3236       const double *coords=getCoords()->getConstPointer();
3237       const int *connec=getNodalConnectivity()->getConstPointer();
3238       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3239       for(int iel=0;iel<nbelem;iel++)
3240         {
3241           ipt=connec_index[iel];
3242           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3243           area_vol[iel]=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[iel+1]-ipt-1,coords,dim_space);
3244         }
3245       if(isAbs)
3246         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3247     }
3248   else
3249     {
3250       area_vol[0]=std::numeric_limits<double>::max();
3251     }
3252   return field.retn();
3253 }
3254
3255 /*!
3256  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3257  * mesh.<br>
3258  * For 1D cells, the returned array contains lengths.<br>
3259  * For 2D cells, the returned array contains areas.<br>
3260  * For 3D cells, the returned array contains volumes.
3261  * This method avoids building explicitly a part of \a this mesh to perform the work.
3262  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3263  *         orientation, i.e. the volume is always positive.
3264  *  \param [in] begin - an array of cell ids of interest.
3265  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3266  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3267  *          delete this array using decrRef() as it is no more needed.
3268  * 
3269  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3270  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3271  *  \sa getMeasureField()
3272  */
3273 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3274 {
3275   std::string name="PartMeasureOfMesh_";
3276   name+=getName();
3277   int nbelem=(int)std::distance(begin,end);
3278   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3279   array->setName(name.c_str());
3280   array->alloc(nbelem,1);
3281   double *area_vol=array->getPointer();
3282   if(getMeshDimension()!=-1)
3283     {
3284       int ipt;
3285       INTERP_KERNEL::NormalizedCellType type;
3286       int dim_space=getSpaceDimension();
3287       const double *coords=getCoords()->getConstPointer();
3288       const int *connec=getNodalConnectivity()->getConstPointer();
3289       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3290       for(const int *iel=begin;iel!=end;iel++)
3291         {
3292           ipt=connec_index[*iel];
3293           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3294           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3295         }
3296       if(isAbs)
3297         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3298     }
3299   else
3300     {
3301       area_vol[0]=std::numeric_limits<double>::max();
3302     }
3303   return array.retn();
3304 }
3305
3306 /*!
3307  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3308  * \a this one. The returned field contains the dual cell volume for each corresponding
3309  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3310  *  the dual mesh in P1 sens of \a this.<br>
3311  * For 1D cells, the returned field contains lengths.<br>
3312  * For 2D cells, the returned field contains areas.<br>
3313  * For 3D cells, the returned field contains volumes.
3314  * This method is useful to check "P1*" conservative interpolators.
3315  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3316  *         orientation, i.e. the volume is always positive.
3317  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3318  *          nodes and one time. The caller is to delete this array using decrRef() as
3319  *          it is no more needed.
3320  */
3321 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3322 {
3323   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3324   std::string name="MeasureOnNodeOfMesh_";
3325   name+=getName();
3326   int nbNodes=getNumberOfNodes();
3327   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3328   double cst=1./((double)getMeshDimension()+1.);
3329   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3330   array->alloc(nbNodes,1);
3331   double *valsToFill=array->getPointer();
3332   std::fill(valsToFill,valsToFill+nbNodes,0.);
3333   const double *values=tmp->getArray()->getConstPointer();
3334   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3336   getReverseNodalConnectivity(da,daInd);
3337   const int *daPtr=da->getConstPointer();
3338   const int *daIPtr=daInd->getConstPointer();
3339   for(int i=0;i<nbNodes;i++)
3340     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3341       valsToFill[i]+=cst*values[*cell];
3342   ret->setMesh(this);
3343   ret->setArray(array);
3344   return ret.retn();
3345 }
3346
3347 /*!
3348  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3349  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3350  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3351  * and are normalized.
3352  * <br> \a this can be either 
3353  * - a  2D mesh in 2D or 3D space or 
3354  * - an 1D mesh in 2D space.
3355  * 
3356  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3357  *          cells and one time. The caller is to delete this field using decrRef() as
3358  *          it is no more needed.
3359  *  \throw If the nodal connectivity of cells is not defined.
3360  *  \throw If the coordinates array is not set.
3361  *  \throw If the mesh dimension is not set.
3362  *  \throw If the mesh and space dimension is not as specified above.
3363  */
3364 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3365 {
3366   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3367     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3368   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3369   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3370   int nbOfCells=getNumberOfCells();
3371   int nbComp=getMeshDimension()+1;
3372   array->alloc(nbOfCells,nbComp);
3373   double *vals=array->getPointer();
3374   const int *connI=_nodal_connec_index->getConstPointer();
3375   const int *conn=_nodal_connec->getConstPointer();
3376   const double *coords=_coords->getConstPointer();
3377   if(getMeshDimension()==2)
3378     {
3379       if(getSpaceDimension()==3)
3380         {
3381           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3382           const double *locPtr=loc->getConstPointer();
3383           for(int i=0;i<nbOfCells;i++,vals+=3)
3384             {
3385               int offset=connI[i];
3386               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3387               double n=INTERP_KERNEL::norm<3>(vals);
3388               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3389             }
3390         }
3391       else
3392         {
3393           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3394           const double *isAbsPtr=isAbs->getArray()->begin();
3395           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3396             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3397         }
3398     }
3399   else//meshdimension==1
3400     {
3401       double tmp[2];
3402       for(int i=0;i<nbOfCells;i++)
3403         {
3404           int offset=connI[i];
3405           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3406           double n=INTERP_KERNEL::norm<2>(tmp);
3407           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3408           *vals++=-tmp[1];
3409           *vals++=tmp[0];
3410         }
3411     }
3412   ret->setArray(array);
3413   ret->setMesh(this);
3414   ret->synchronizeTimeWithSupport();
3415   return ret.retn();
3416 }
3417
3418 /*!
3419  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3420  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3421  * and are normalized.
3422  * <br> \a this can be either 
3423  * - a  2D mesh in 2D or 3D space or 
3424  * - an 1D mesh in 2D space.
3425  * 
3426  * This method avoids building explicitly a part of \a this mesh to perform the work.
3427  *  \param [in] begin - an array of cell ids of interest.
3428  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3429  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3430  *          cells and one time. The caller is to delete this field using decrRef() as
3431  *          it is no more needed.
3432  *  \throw If the nodal connectivity of cells is not defined.
3433  *  \throw If the coordinates array is not set.
3434  *  \throw If the mesh dimension is not set.
3435  *  \throw If the mesh and space dimension is not as specified above.
3436  *  \sa buildOrthogonalField()
3437  *
3438  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3439  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3440  */
3441 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3442 {
3443   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3444     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3445   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3446   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3447   std::size_t nbelems=std::distance(begin,end);
3448   int nbComp=getMeshDimension()+1;
3449   array->alloc((int)nbelems,nbComp);
3450   double *vals=array->getPointer();
3451   const int *connI=_nodal_connec_index->getConstPointer();
3452   const int *conn=_nodal_connec->getConstPointer();
3453   const double *coords=_coords->getConstPointer();
3454   if(getMeshDimension()==2)
3455     {
3456       if(getSpaceDimension()==3)
3457         {
3458           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3459           const double *locPtr=loc->getConstPointer();
3460           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3461             {
3462               int offset=connI[*i];
3463               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3464               double n=INTERP_KERNEL::norm<3>(vals);
3465               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3466             }
3467         }
3468       else
3469         {
3470           for(std::size_t i=0;i<nbelems;i++)
3471             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3472         }
3473     }
3474   else//meshdimension==1
3475     {
3476       double tmp[2];
3477       for(const int *i=begin;i!=end;i++)
3478         {
3479           int offset=connI[*i];
3480           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3481           double n=INTERP_KERNEL::norm<2>(tmp);
3482           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3483           *vals++=-tmp[1];
3484           *vals++=tmp[0];
3485         }
3486     }
3487   ret->setArray(array);
3488   ret->setMesh(this);
3489   ret->synchronizeTimeWithSupport();
3490   return ret.retn();
3491 }
3492
3493 /*!
3494  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3495  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3496  * and are \b not normalized.
3497  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3498  *          cells and one time. The caller is to delete this field using decrRef() as
3499  *          it is no more needed.
3500  *  \throw If the nodal connectivity of cells is not defined.
3501  *  \throw If the coordinates array is not set.
3502  *  \throw If \a this->getMeshDimension() != 1.
3503  *  \throw If \a this mesh includes cells of type other than SEG2.
3504  */
3505 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3506 {
3507    if(getMeshDimension()!=1)
3508     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3509    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3510      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3511    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3512    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3513    int nbOfCells=getNumberOfCells();
3514    int spaceDim=getSpaceDimension();
3515    array->alloc(nbOfCells,spaceDim);
3516    double *pt=array->getPointer();
3517    const double *coo=getCoords()->getConstPointer();
3518    std::vector<int> conn;
3519    conn.reserve(2);
3520    for(int i=0;i<nbOfCells;i++)
3521      {
3522        conn.resize(0);
3523        getNodeIdsOfCell(i,conn);
3524        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3525      }
3526    ret->setArray(array);
3527    ret->setMesh(this);
3528    ret->synchronizeTimeWithSupport();
3529    return ret.retn();   
3530 }
3531
3532 /*!
3533  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3534  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3535  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3536  * from. If a result face is shared by two 3D cells, then the face in included twice in
3537  * the result mesh.
3538  *  \param [in] origin - 3 components of a point defining location of the plane.
3539  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3540  *         must be greater than 1e-6.
3541  *  \param [in] eps - half-thickness of the plane.
3542  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3543  *         producing correspondent 2D cells. The caller is to delete this array
3544  *         using decrRef() as it is no more needed.
3545  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3546  *         not share the node coordinates array with \a this mesh. The caller is to
3547  *         delete this mesh using decrRef() as it is no more needed.  
3548  *  \throw If the coordinates array is not set.
3549  *  \throw If the nodal connectivity of cells is not defined.
3550  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3551  *  \throw If magnitude of \a vec is less than 1e-6.
3552  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3553  *  \throw If \a this includes quadratic cells.
3554  */
3555 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3556 {
3557   checkFullyDefined();
3558   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3559     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3560   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3561   if(candidates->empty())
3562     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3563   std::vector<int> nodes;
3564   DataArrayInt *cellIds1D=0;
3565   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3566   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3567   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3568   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3569   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3570   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3571   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3572   revDesc2=0; revDescIndx2=0;
3573   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3574   revDesc1=0; revDescIndx1=0;
3575   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3576   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3577   //
3578   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3579   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3580     cut3DCurve[*it]=-1;
3581   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3582   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3583   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3584                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3585                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3586   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3587   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3588   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3589   if(cellIds2->empty())
3590     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3591   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3592   ret->setCoords(mDesc1->getCoords());
3593   ret->setConnectivity(conn,connI,true);
3594   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3595   return ret.retn();
3596 }
3597
3598 /*!
3599  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3600 addition to the mesh, returns a new DataArrayInt, of length equal to the number of 1D cells in the result mesh, holding, for each cell in the result mesh, an id of a 2D cell it comes
3601 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3602 the result mesh.
3603  *  \param [in] origin - 3 components of a point defining location of the plane.
3604  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3605  *         must be greater than 1e-6.
3606  *  \param [in] eps - half-thickness of the plane.
3607  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3608  *         producing correspondent segments. The caller is to delete this array
3609  *         using decrRef() as it is no more needed.
3610  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3611  *         mesh in 3D space. This mesh does not share the node coordinates array with
3612  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3613  *         no more needed. 
3614  *  \throw If the coordinates array is not set.
3615  *  \throw If the nodal connectivity of cells is not defined.
3616  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3617  *  \throw If magnitude of \a vec is less than 1e-6.
3618  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3619  *  \throw If \a this includes quadratic cells.
3620  */
3621 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3622 {
3623   checkFullyDefined();
3624   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3625     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3626   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3627   if(candidates->empty())
3628     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3629   std::vector<int> nodes;
3630   DataArrayInt *cellIds1D=0;
3631   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3632   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3633   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3634   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3635   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3636   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3637   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3638   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3639   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3640   //
3641   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3642   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3643     cut3DCurve[*it]=-1;
3644   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3645   int ncellsSub=subMesh->getNumberOfCells();
3646   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3647   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3648                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3649                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3650   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3651   conn->alloc(0,1);
3652   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3653   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3654   for(int i=0;i<ncellsSub;i++)
3655     {
3656       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3657         {
3658           if(cut3DSurf[i].first!=-2)
3659             {
3660               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3661               connI->pushBackSilent(conn->getNumberOfTuples());
3662               cellIds2->pushBackSilent(i);
3663             }
3664           else
3665             {
3666               int cellId3DSurf=cut3DSurf[i].second;
3667               int offset=nodalI[cellId3DSurf]+1;
3668               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3669               for(int j=0;j<nbOfEdges;j++)
3670                 {
3671                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3672                   connI->pushBackSilent(conn->getNumberOfTuples());
3673                   cellIds2->pushBackSilent(cellId3DSurf);
3674                 }
3675             }
3676         }
3677     }
3678   if(cellIds2->empty())
3679     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3680   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3681   ret->setCoords(mDesc1->getCoords());
3682   ret->setConnectivity(conn,connI,true);
3683   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3684   return ret.retn();
3685 }
3686
3687 /*!
3688  * Finds cells whose bounding boxes intersect a given plane.
3689  *  \param [in] origin - 3 components of a point defining location of the plane.
3690  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3691  *         must be greater than 1e-6.
3692  *  \param [in] eps - half-thickness of the plane.
3693  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3694  *         cells. The caller is to delete this array using decrRef() as it is no more
3695  *         needed.
3696  *  \throw If the coordinates array is not set.
3697  *  \throw If the nodal connectivity of cells is not defined.
3698  *  \throw If \a this->getSpaceDimension() != 3.
3699  *  \throw If magnitude of \a vec is less than 1e-6.
3700  *  \sa buildSlice3D()
3701  */
3702 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3703 {
3704   checkFullyDefined();
3705   if(getSpaceDimension()!=3)
3706     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3707   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3708   if(normm<1e-6)
3709     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3710   double vec2[3];
3711   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3712   double angle=acos(vec[2]/normm);
3713   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3714   double bbox[6];
3715   if(angle>eps)
3716     {
3717       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3718       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3719       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3720       mw->setCoords(coo);
3721       mw->getBoundingBox(bbox);
3722       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3723       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3724     }
3725   else
3726     {
3727       getBoundingBox(bbox);
3728       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3729       cellIds=getCellsInBoundingBox(bbox,eps);
3730     }
3731   return cellIds.retn();
3732 }
3733
3734 /*!
3735  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3736  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3737  * No consideration of coordinate is done by this method.
3738  * A 1D mesh is said contiguous if : a cell i with nodal connectivity (k,p) the cell i+1 the nodal connectivity should be (p,m)
3739  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3740  */
3741 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3742 {
3743   if(getMeshDimension()!=1)
3744     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3745   int nbCells=getNumberOfCells();
3746   if(nbCells<1)
3747     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3748   const int *connI=_nodal_connec_index->getConstPointer();
3749   const int *conn=_nodal_connec->getConstPointer();
3750   int ref=conn[connI[0]+2];
3751   for(int i=1;i<nbCells;i++)
3752     {
3753       if(conn[connI[i]+1]!=ref)
3754         return false;
3755       ref=conn[connI[i]+2];
3756     }
3757   return true;
3758 }
3759
3760 /*!
3761  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3762  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3763  * \param pt reference point of the line
3764  * \param v normalized director vector of the line
3765  * \param eps max precision before throwing an exception
3766  * \param res output of size this->getNumberOfCells
3767  */
3768 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3769 {
3770   if(getMeshDimension()!=1)
3771     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3772    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3773      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3774    if(getSpaceDimension()!=3)
3775      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3776    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3777    const double *fPtr=f->getArray()->getConstPointer();
3778    double tmp[3];
3779    for(int i=0;i<getNumberOfCells();i++)
3780      {
3781        const double *tmp1=fPtr+3*i;
3782        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3783        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3784        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3785        double n1=INTERP_KERNEL::norm<3>(tmp);
3786        n1/=INTERP_KERNEL::norm<3>(tmp1);
3787        if(n1>eps)
3788          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3789      }
3790    const double *coo=getCoords()->getConstPointer();
3791    for(int i=0;i<getNumberOfNodes();i++)
3792      {
3793        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3794        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3795        res[i]=std::accumulate(tmp,tmp+3,0.);
3796      }
3797 }
3798
3799 /*!
3800  * This method computes the distance from a point \a pt to \a this and the first \a cellId in \a this corresponding to the returned distance. 
3801  * \a this is expected to be a mesh so that its space dimension is equal to its
3802  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3803  * Distance from \a ptBg to \a ptEnd is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
3804  
3805  * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3806  * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3807  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3808  *
3809  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3810  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3811  *
3812  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3813  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3814  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3815  * \return the positive value of the distance.
3816  * \throw if distance from \a ptBg to \a ptEnd is not equal to the space dimension. An exception is also thrown if mesh dimension of \a this is not equal to space
3817  * dimension - 1.
3818  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3819  */
3820 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
3821 {
3822   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3823   if(meshDim!=spaceDim-1)
3824     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3825   if(meshDim!=2 && meshDim!=1)
3826     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3827   checkFullyDefined();
3828   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3829     { std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoint : input point has to have dimension equal to the space dimension of this (" << spaceDim << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
3830   DataArrayInt *ret1=0;
3831   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3832   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3833   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3834   cellId=*ret1Safe->begin();
3835   return *ret0->begin();
3836 }
3837
3838 /*!
3839  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3840  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3841  * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3842  * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3843  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3844  * 
3845  * \a this is expected to be a mesh so that its space dimension is equal to its
3846  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3847  * Number of components of \a pts is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
3848  *
3849  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3850  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3851  *
3852  * \param [in] pts the list of points in which each tuple represents a point
3853  * \param [out] cellIds a newly allocated object that tells for each point in \a pts the first cell id in \a this that minimizes the distance.
3854  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3855  * \throw if number of components of \a pts is not equal to the space dimension.
3856  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3857  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3858  */
3859 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
3860 {
3861   if(!pts)
3862     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3863   pts->checkAllocated();
3864   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3865   if(meshDim!=spaceDim-1)
3866     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3867   if(meshDim!=2 && meshDim!=1)
3868     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3869   if(pts->getNumberOfComponents()!=spaceDim)
3870     {
3871       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3872       throw INTERP_KERNEL::Exception(oss.str().c_str());
3873     }
3874   checkFullyDefined();
3875   int nbCells=getNumberOfCells();
3876   if(nbCells==0)
3877     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3878   int nbOfPts=pts->getNumberOfTuples();
3879   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3881   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3882   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3883   std::vector<double> bbox;
3884   getBoundingBoxForBBTree(bbox);
3885   switch(spaceDim)
3886     {
3887     case 3:
3888       {
3889         BBTreeDst<3> myTree(&bbox[0],0,0,nbCells);
3890         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3891           {
3892             double x=std::numeric_limits<double>::max();
3893             std::vector<int> elems;
3894             myTree.getMinDistanceOfMax(ptsPtr,x);
3895             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3896             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3897           }
3898         break;
3899       }
3900     case 2:
3901       {
3902         BBTreeDst<2> myTree(&bbox[0],0,0,nbCells);
3903         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3904           {
3905             double x=std::numeric_limits<double>::max();
3906             std::vector<int> elems;
3907             myTree.getMinDistanceOfMax(ptsPtr,x);
3908             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3909             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3910           }
3911         break;
3912       }
3913     default:
3914       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3915     }
3916   cellIds=ret1.retn();
3917   return ret0.retn();
3918 }
3919
3920 /*!
3921  * \param [in] pt the start pointer (included) of the coordinates of the point
3922  * \param [in] cellIdsBg the start pointer (included) of cellIds
3923  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3924  * \param [in] nc nodal connectivity
3925  * \param [in] ncI nodal connectivity index
3926  * \param [in,out] ret0 the min distance between \a this and the external input point
3927  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3928  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3929  */
3930 void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId) throw(INTERP_KERNEL::Exception)
3931 {
3932   cellId=-1;
3933   ret0=std::numeric_limits<double>::max();
3934   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3935     {
3936       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3937         {
3938         case INTERP_KERNEL::NORM_TRI3:
3939           {
3940             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3941             if(tmp<ret0)
3942               { ret0=tmp; cellId=*zeCell; }
3943             break;
3944           }
3945         case INTERP_KERNEL::NORM_QUAD4:
3946         case INTERP_KERNEL::NORM_POLYGON:
3947           {
3948             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3949             if(tmp<ret0)
3950               { ret0=tmp; cellId=*zeCell; }
3951             break;
3952           }
3953         default:
3954           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3955         }
3956     }
3957 }
3958
3959 /*!
3960  * \param [in] pt the start pointer (included) of the coordinates of the point
3961  * \param [in] cellIdsBg the start pointer (included) of cellIds
3962  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3963  * \param [in] nc nodal connectivity
3964  * \param [in] ncI nodal connectivity index
3965  * \param [in,out] ret0 the min distance between \a this and the external input point
3966  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3967  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3968  */
3969 void MEDCouplingUMesh::DistanceToPoint2DCurveAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId) throw(INTERP_KERNEL::Exception)
3970 {
3971   cellId=-1;
3972   ret0=std::numeric_limits<double>::max();
3973   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3974     {
3975        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3976         {
3977         case INTERP_KERNEL::NORM_SEG2:
3978           {
3979             std::size_t uselessEntry=0;
3980             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
3981             tmp=sqrt(tmp);
3982             if(tmp<ret0)
3983               { ret0=tmp; cellId=*zeCell; }
3984             break;
3985           }
3986         default:
3987           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3988         }
3989     }
3990 }
3991
3992 /*!
3993  * Finds cells in contact with a ball (i.e. a point with precision). 
3994  * \warning This method is suitable if the caller intends to evaluate only one
3995  *          point, for more points getCellsContainingPoints() is recommended as it is
3996  *          faster. 
3997  *  \param [in] pos - array of coordinates of the ball central point.
3998  *  \param [in] eps - ball radius.
3999  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4000  *         if there are no such cells.
4001  *  \throw If the coordinates array is not set.
4002  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4003  */
4004 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4005 {
4006   std::vector<int> elts;
4007   getCellsContainingPoint(pos,eps,elts);
4008   if(elts.empty())
4009     return -1;
4010   return elts.front();
4011 }
4012
4013 /*!
4014  * Finds cells in contact with a ball (i.e. a point with precision).
4015  * \warning This method is suitable if the caller intends to evaluate only one
4016  *          point, for more points getCellsContainingPoints() is recommended as it is
4017  *          faster. 
4018  *  \param [in] pos - array of coordinates of the ball central point.
4019  *  \param [in] eps - ball radius.
4020  *  \param [in,out] elts - vector returning ids of the found cells. It is cleared
4021  *         before inserting ids.
4022  *  \throw If the coordinates array is not set.
4023  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4024  *
4025  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4026  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4027  */
4028 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4029 {
4030   std::vector<int> eltsIndex;
4031   getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
4032 }
4033
4034 /// @cond INTERNAL
4035
4036 namespace ParaMEDMEM
4037 {
4038   template<const int SPACEDIMM>
4039   class DummyClsMCUG
4040   {
4041   public:
4042     static const int MY_SPACEDIM=SPACEDIMM;
4043     static const int MY_MESHDIM=8;
4044     typedef int MyConnType;
4045     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4046     // begin
4047     // useless, but for windows compilation ...
4048     const double* getCoordinatesPtr() const { return 0; }
4049     const int* getConnectivityPtr() const { return 0; }
4050     const int* getConnectivityIndexPtr() const { return 0; }
4051     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4052     // end
4053   };
4054
4055   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4056   {
4057     INTERP_KERNEL::Edge *ret=0;
4058     switch(typ)
4059       {
4060       case INTERP_KERNEL::NORM_SEG2:
4061         {
4062           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4063           break;
4064         }
4065       case INTERP_KERNEL::NORM_SEG3:
4066         {
4067           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4068           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4069           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4070           bool colinearity=inters.areColinears();
4071           delete e1; delete e2;
4072           if(colinearity)
4073             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4074           else
4075             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4076           mapp2[bg[2]].second=false;
4077           break;
4078         }
4079       default:
4080         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4081       }
4082     return ret;
4083   }
4084
4085   /*!
4086    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed be the sub set of cells in 'candidates' and the global mesh 'mDesc'.
4087    * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4088    * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4089    */
4090   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4091   {
4092     mapp.clear();
4093     std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;//bool is for a flag specifying if node is boundary (true) or only a middle for SEG3.
4094     const double *coo=mDesc->getCoords()->getConstPointer();
4095     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4096     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4097     std::set<int> s;
4098     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4099       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4100     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4101       {
4102         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4103         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4104       }
4105     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4106     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4107       {
4108         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4109         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4110       }
4111     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4112       {
4113         if((*it2).second.second)
4114           mapp[(*it2).second.first]=(*it2).first;
4115         ((*it2).second.first)->decrRef();
4116       }
4117     return ret;
4118   }
4119
4120   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4121   {
4122     if(nodeId>=offset2)
4123       {
4124         int locId=nodeId-offset2;
4125         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4126       }
4127     if(nodeId>=offset1)
4128       {
4129         int locId=nodeId-offset1;
4130         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4131       }
4132     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4133   }
4134
4135   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4136                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4137                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4138   {
4139     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4140       {
4141         int eltId1=abs(*desc1)-1;
4142         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4143           {
4144             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4145             if(it==mappRev.end())
4146               {
4147                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4148                 mapp[node]=*it1;
4149                 mappRev[*it1]=node;
4150               }
4151           }
4152       }
4153   }
4154 }
4155
4156 /// @endcond
4157
4158 template<int SPACEDIM>
4159 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4160                                                    double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4161 {
4162   std::vector<double> bbox;
4163   eltsIndex.resize(nbOfPoints+1);
4164   eltsIndex[0]=0;
4165   elts.clear();
4166   getBoundingBoxForBBTree(bbox);
4167   int nbOfCells=getNumberOfCells();
4168   const int *conn=_nodal_connec->getConstPointer();
4169   const int *connI=_nodal_connec_index->getConstPointer();
4170   double bb[2*SPACEDIM];
4171   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4172   for(int i=0;i<nbOfPoints;i++)
4173     {
4174       eltsIndex[i+1]=eltsIndex[i];
4175       for(int j=0;j<SPACEDIM;j++)
4176         {
4177           bb[2*j]=pos[SPACEDIM*i+j];
4178           bb[2*j+1]=pos[SPACEDIM*i+j];
4179         }
4180       std::vector<int> candidates;
4181       myTree.getIntersectingElems(bb,candidates);
4182       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4183         {
4184           int sz=connI[(*iter)+1]-connI[*iter]-1;
4185           if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4186                                                                                                (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4187                                                                                                coords,conn+connI[*iter]+1,sz,eps))
4188             {
4189               eltsIndex[i+1]++;
4190               elts.push_back(*iter);
4191             }
4192         }
4193     }
4194 }
4195 /*!
4196  * Finds cells in contact with several balls (i.e. points with precision).
4197  * This method is an extension of getCellContainingPoint() and
4198  * getCellsContainingPoint() for the case of multiple points.
4199  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4200  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4201  *         this->getSpaceDimension() * \a nbOfPoints 
4202  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4203  *  \param [in] eps - radius of balls (i.e. the precision).
4204  *  \param [in,out] elts - vector returning ids of found cells.
4205  *  \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4206  *         dividing cell ids in \a elts into groups each referring to one
4207  *         point. Its every element (except the last one) is an index pointing to the
4208  *         first id of a group of cells. For example cells in contact with the *i*-th
4209  *         point are described by following range of indices:
4210  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4211  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4212  *         Number of cells in contact with the *i*-th point is
4213  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4214  *  \throw If the coordinates array is not set.
4215  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4216  *
4217  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4218  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4219  */
4220 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4221                                                 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4222 {
4223   int spaceDim=getSpaceDimension();
4224   int mDim=getMeshDimension();
4225   if(spaceDim==3)
4226     {
4227       if(mDim==3)
4228         {
4229           const double *coords=_coords->getConstPointer();
4230           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4231         }
4232       /*else if(mDim==2)
4233         {
4234           
4235         }*/
4236       else
4237         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4238     }
4239   else if(spaceDim==2)
4240     {
4241       if(mDim==2)
4242         {
4243           const double *coords=_coords->getConstPointer();
4244           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4245         }
4246       else
4247         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4248     }
4249   else if(spaceDim==1)
4250     {
4251       if(mDim==1)
4252         {
4253           const double *coords=_coords->getConstPointer();
4254           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4255         }
4256       else
4257         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4258     }
4259   else
4260     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4261 }
4262
4263 /*!
4264  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4265  * least two its edges intersect each other anywhere except their extremities. An
4266  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4267  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4268  *         cleared before filling in.
4269  *  \param [in] eps - precision.
4270  *  \throw If \a this->getMeshDimension() != 2.
4271  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4272  */
4273 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4274 {
4275   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4276   if(getMeshDimension()!=2)
4277     throw INTERP_KERNEL::Exception(msg);
4278   int spaceDim=getSpaceDimension();
4279   if(spaceDim!=2 && spaceDim!=3)
4280     throw INTERP_KERNEL::Exception(msg);
4281   const int *conn=_nodal_connec->getConstPointer();
4282   const int *connI=_nodal_connec_index->getConstPointer();
4283   int nbOfCells=getNumberOfCells();
4284   std::vector<double> cell2DinS2;
4285   for(int i=0;i<nbOfCells;i++)
4286     {
4287       int offset=connI[i];
4288       int nbOfNodesForCell=connI[i+1]-offset-1;
4289       if(nbOfNodesForCell<=3)
4290         continue;
4291       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4292       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4293       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4294         cells.push_back(i);
4295       cell2DinS2.clear();
4296     }
4297 }
4298
4299 /*!
4300  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4301  *
4302  * This method expects that space dimension is equal to 2 and mesh dimension is equal to 2 too. If it is not the case an INTERP_KERNEL::Exception will be thrown.
4303  * This method works only for linear 2D cells. If there is any of non linear cells (INTERP_KERNEL::NORM_QUAD8 for example) an INTERP_KERNEL::Exception will be thrown too.
4304  * 
4305  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4306  * This convex envelop is computed using Jarvis march algorithm.
4307  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4308  * Only connectivity of some cells could be modified if those cells were not representing a convex envelop. If a cell already equals its convex envelop (regardless orientation)
4309  * its connectivity will remain unchanged. If the computation leads to a modification of nodal connectivity of a cell its geometric type will be modified to INTERP_KERNEL::NORM_POLYGON.
4310  *
4311  * \return a newly allocated array containing cellIds that have been modified if any. If no cells have been impacted by this method NULL is returned.
4312  */
4313 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4314 {
4315   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4316     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4317   checkFullyDefined();
4318   const double *coords=getCoords()->getConstPointer();
4319   int nbOfCells=getNumberOfCells();
4320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4321   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4322   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4323   int *workIndexOut=nodalConnecIndexOut->getPointer();
4324   *workIndexOut=0;
4325   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4326   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4327   std::set<INTERP_KERNEL::NormalizedCellType> types;
4328   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4329   isChanged->alloc(0,1);
4330   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4331     {
4332       int pos=nodalConnecOut->getNumberOfTuples();
4333       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4334         isChanged->pushBackSilent(i);
4335       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4336       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4337     }
4338   if(isChanged->empty())
4339     return 0;
4340   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4341   _types=types;
4342   return isChanged.retn();
4343 }
4344
4345 /*!
4346  * This method is \b NOT const because it can modify \a this.
4347  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4348  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4349  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4350  * \b 1 for translation and rotation around point of 'mesh1D'.
4351  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4352  */
4353 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4354 {
4355   checkFullyDefined();
4356   mesh1D->checkFullyDefined();
4357   if(!mesh1D->isContiguous1D())
4358     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4359   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4360     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4361   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4362     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4363   if(mesh1D->getMeshDimension()!=1)
4364     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4365   bool isQuad=false;
4366   if(isPresenceOfQuadratic())
4367     {
4368       if(mesh1D->isFullyQuadratic())
4369         isQuad=true;
4370       else
4371         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4372     }
4373   zipCoords();
4374   int oldNbOfNodes=getNumberOfNodes();
4375   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4376   switch(policy)
4377     {
4378     case 0:
4379       {
4380         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4381         break;
4382       }
4383     case 1:
4384       {
4385         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4386         break;
4387       }
4388     default:
4389       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4390     }
4391   setCoords(newCoords);
4392   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4393   updateTime();
4394   return ret.retn();
4395 }
4396
4397 /*!
4398  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4399  * If it is not the case an exception will be thrown.
4400  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4401  * intersection of plane defined by ('origin','vec').
4402  * This method has one in/out parameter : 'cut3DCurve'.
4403  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4404  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4405  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4406  * This method will throw an exception if \a this contains a non linear segment.
4407  */
4408 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4409 {
4410   checkFullyDefined();
4411   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4412     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4413   int ncells=getNumberOfCells();
4414   int nnodes=getNumberOfNodes();
4415   double vec2[3],vec3[3],vec4[3];
4416   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4417   if(normm<1e-6)
4418     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4419   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4420   const int *conn=_nodal_connec->getConstPointer();
4421   const int *connI=_nodal_connec_index->getConstPointer();
4422   const double *coo=_coords->getConstPointer();
4423   std::vector<double> addCoo;
4424   for(int i=0;i<ncells;i++)
4425     {
4426       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4427         {
4428           if(cut3DCurve[i]==-2)
4429             {
4430               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4431               vec3[0]=coo[3*endd]-coo[3*st]; vec3[1]=coo[3*endd+1]-coo[3*st+1]; vec3[2]=coo[3*endd+2]-coo[3*st+2];
4432               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4433               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4434               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4435                 {
4436                   const double *st2=coo+3*st;
4437                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4438                   double pos=-(vec4[0]*vec2[0]+vec4[1]*vec2[1]+vec4[2]*vec2[2])/((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2]));
4439                   if(pos>eps && pos<1-eps)
4440                     {
4441                       int nNode=((int)addCoo.size())/3;
4442                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4443                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4444                       cut3DCurve[i]=nnodes+nNode;
4445                     }
4446                 }
4447             }
4448         }
4449       else
4450         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4451     }
4452   if(!addCoo.empty())
4453     {
4454       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4455       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4456       coo2->alloc(newNbOfNodes,3);
4457       double *tmp=coo2->getPointer();
4458       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4459       std::copy(addCoo.begin(),addCoo.end(),tmp);
4460       DataArrayDouble::SetArrayIn(coo2,_coords);
4461     }
4462 }
4463
4464 /*!
4465  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4466  * \param mesh1D is the input 1D mesh used for translation computation.
4467  * \return newCoords new coords filled by this method. 
4468  */
4469 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4470 {
4471   int oldNbOfNodes=getNumberOfNodes();
4472   int nbOf1DCells=mesh1D->getNumberOfCells();
4473   int spaceDim=getSpaceDimension();
4474   DataArrayDouble *ret=DataArrayDouble::New();
4475   std::vector<bool> isQuads;
4476   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4477   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4478   double *retPtr=ret->getPointer();
4479   const double *coords=getCoords()->getConstPointer();
4480   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4481   std::vector<int> v;
4482   std::vector<double> c;
4483   double vec[3];
4484   v.reserve(3);
4485   c.reserve(6);
4486   for(int i=0;i<nbOf1DCells;i++)
4487     {
4488       v.resize(0);
4489       mesh1D->getNodeIdsOfCell(i,v);
4490       c.resize(0);
4491       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4492       mesh1D->getCoordinatesOfNode(v[0],c);
4493       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4494       for(int j=0;j<oldNbOfNodes;j++)
4495         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4496       if(isQuad)
4497         {
4498           c.resize(0);
4499           mesh1D->getCoordinatesOfNode(v[1],c);
4500           mesh1D->getCoordinatesOfNode(v[0],c);
4501           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4502           for(int j=0;j<oldNbOfNodes;j++)
4503             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4504         }
4505     }
4506   ret->copyStringInfoFrom(*getCoords());
4507   return ret;
4508 }
4509
4510 /*!
4511  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4512  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4513  * \return newCoords new coords filled by this method. 
4514  */
4515 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4516 {
4517   if(mesh1D->getSpaceDimension()==2)
4518     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4519   if(mesh1D->getSpaceDimension()==3)
4520     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4521   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4522 }
4523
4524 /*!
4525  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4526  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4527  * \return newCoords new coords filled by this method. 
4528  */
4529 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4530 {
4531   if(isQuad)
4532     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4533   int oldNbOfNodes=getNumberOfNodes();
4534   int nbOf1DCells=mesh1D->getNumberOfCells();
4535   if(nbOf1DCells<2)
4536     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4537   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4538   int nbOfLevsInVec=nbOf1DCells+1;
4539   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4540   double *retPtr=ret->getPointer();
4541   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4542   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4543   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4544   tmp->setCoords(tmp2);
4545   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4546   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4547   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4548   for(int i=1;i<nbOfLevsInVec;i++)
4549     {
4550       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4551       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4552       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4553       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4554       tmp->translate(vec);
4555       double tmp3[2],radius,alpha,alpha0;
4556       const double *p0=i+1<nbOfLevsInVec?begin:third;
4557       const double *p1=i+1<nbOfLevsInVec?end:begin;
4558       const double *p2=i+1<nbOfLevsInVec?third:end;
4559       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4560       double cosangle=i+1<nbOfLevsInVec?(p0[0]-tmp3[0])*(p1[0]-tmp3[0])+(p0[1]-tmp3[1])*(p1[1]-tmp3[1]):(p2[0]-tmp3[0])*(p1[0]-tmp3[0])+(p2[1]-tmp3[1])*(p1[1]-tmp3[1]);
4561       double angle=acos(cosangle/(radius*radius));
4562       tmp->rotate(end,0,angle);
4563       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4564     }
4565   return ret.retn();
4566 }
4567
4568 /*!
4569  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4570  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4571  * \return newCoords new coords filled by this method. 
4572  */
4573 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4574 {
4575   if(isQuad)
4576     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4577   int oldNbOfNodes=getNumberOfNodes();
4578   int nbOf1DCells=mesh1D->getNumberOfCells();
4579   if(nbOf1DCells<2)
4580     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4581   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4582   int nbOfLevsInVec=nbOf1DCells+1;
4583   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4584   double *retPtr=ret->getPointer();
4585   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4586   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4587   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4588   tmp->setCoords(tmp2);
4589   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4590   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4591   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4592   for(int i=1;i<nbOfLevsInVec;i++)
4593     {
4594       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4595       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4596       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4597       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4598       tmp->translate(vec);
4599       double tmp3[2],radius,alpha,alpha0;
4600       const double *p0=i+1<nbOfLevsInVec?begin:third;
4601       const double *p1=i+1<nbOfLevsInVec?end:begin;
4602       const double *p2=i+1<nbOfLevsInVec?third:end;
4603       double vecPlane[3]={
4604         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4605         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4606         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4607       };
4608       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4609       if(norm>1.e-7)
4610         {
4611           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4612           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4613           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4614           double s2=norm2;
4615           double c2=cos(asin(s2));
4616           double m[3][3]={
4617             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4618             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4619             {-vec2[1]*s2, vec2[0]*s2, c2}
4620           };
4621           double p0r[3]={m[0][0]*p0[0]+m[0][1]*p0[1]+m[0][2]*p0[2], m[1][0]*p0[0]+m[1][1]*p0[1]+m[1][2]*p0[2], m[2][0]*p0[0]+m[2][1]*p0[1]+m[2][2]*p0[2]};
4622           double p1r[3]={m[0][0]*p1[0]+m[0][1]*p1[1]+m[0][2]*p1[2], m[1][0]*p1[0]+m[1][1]*p1[1]+m[1][2]*p1[2], m[2][0]*p1[0]+m[2][1]*p1[1]+m[2][2]*p1[2]};
4623           double p2r[3]={m[0][0]*p2[0]+m[0][1]*p2[1]+m[0][2]*p2[2], m[1][0]*p2[0]+m[1][1]*p2[1]+m[1][2]*p2[2], m[2][0]*p2[0]+m[2][1]*p2[1]+m[2][2]*p2[2]};
4624           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4625           double cosangle=i+1<nbOfLevsInVec?(p0r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p0r[1]-tmp3[1])*(p1r[1]-tmp3[1]):(p2r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p2r[1]-tmp3[1])*(p1r[1]-tmp3[1]);
4626           double angle=acos(cosangle/(radius*radius));
4627           tmp->rotate(end,vecPlane,angle);
4628           
4629         }
4630       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4631     }
4632   return ret.retn();
4633 }
4634
4635 /*!
4636  * This method is private because not easy to use for end user. This method is const contrary to
4637  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4638  * the coords sorted slice by slice.
4639  * \param isQuad specifies presence of quadratic cells.
4640  */
4641 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4642 {
4643   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4644   int nbOf2DCells=getNumberOfCells();
4645   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4646   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4647   const int *conn=_nodal_connec->getConstPointer();
4648   const int *connI=_nodal_connec_index->getConstPointer();
4649   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4650   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4651   newConnI->alloc(nbOf3DCells+1,1);
4652   int *newConnIPtr=newConnI->getPointer();
4653   *newConnIPtr++=0;
4654   std::vector<int> newc;
4655   for(int j=0;j<nbOf2DCells;j++)
4656     {
4657       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4658       *newConnIPtr++=(int)newc.size();
4659     }
4660   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4661   int *newConnPtr=newConn->getPointer();
4662   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4663   newConnIPtr=newConnI->getPointer();
4664   for(int iz=0;iz<nbOf1DCells;iz++)
4665     {
4666       if(iz!=0)
4667         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4668       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4669         {
4670           int icell=(int)(iter-newc.begin());
4671           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4672             {
4673               if(*iter!=-1)
4674                 *newConnPtr=(*iter)+iz*deltaPerLev;
4675               else
4676                 *newConnPtr=-1;
4677             }
4678           else
4679             *newConnPtr=(*iter);
4680         }
4681     }
4682   ret->setConnectivity(newConn,newConnI,true);
4683   ret->setCoords(getCoords());
4684   return ret;
4685 }
4686
4687 /*!
4688  * Checks if \a this mesh is constituted by only quadratic cells.
4689  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4690  *  \throw If the coordinates array is not set.
4691  *  \throw If the nodal connectivity of cells is not defined.
4692  */
4693 bool MEDCouplingUMesh::isFullyQuadratic() const
4694 {
4695   checkFullyDefined();
4696   bool ret=true;
4697   int nbOfCells=getNumberOfCells();
4698   for(int i=0;i<nbOfCells && ret;i++)
4699     {
4700       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4701       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4702       ret=cm.isQuadratic();
4703     }
4704   return ret;
4705 }
4706
4707 /*!
4708  * Checks if \a this mesh includes any quadratic cell.
4709  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4710  *  \throw If the coordinates array is not set.
4711  *  \throw If the nodal connectivity of cells is not defined.
4712  */
4713 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4714 {
4715   checkFullyDefined();
4716   bool ret=false;
4717   int nbOfCells=getNumberOfCells();
4718   for(int i=0;i<nbOfCells && !ret;i++)
4719     {
4720       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4721       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4722       ret=cm.isQuadratic();
4723     }
4724   return ret;
4725 }
4726
4727 /*!
4728  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4729  * this mesh, it remains unchanged.
4730  *  \throw If the coordinates array is not set.
4731  *  \throw If the nodal connectivity of cells is not defined.
4732  */
4733 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4734 {
4735   checkFullyDefined();
4736   int nbOfCells=getNumberOfCells();
4737   int delta=0;
4738   const int *iciptr=_nodal_connec_index->getConstPointer();
4739   for(int i=0;i<nbOfCells;i++)
4740     {
4741       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4742       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4743       if(cm.isQuadratic())
4744         {
4745           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4746           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4747           if(!cml.isDynamic())
4748             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4749           else
4750             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4751         }
4752     }
4753   if(delta==0)
4754     return ;
4755   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4756   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4757   const int *icptr=_nodal_connec->getConstPointer();
4758   newConn->alloc(getMeshLength()-delta,1);
4759   newConnI->alloc(nbOfCells+1,1);
4760   int *ocptr=newConn->getPointer();
4761   int *ociptr=newConnI->getPointer();
4762   *ociptr=0;
4763   _types.clear();
4764   for(int i=0;i<nbOfCells;i++,ociptr++)
4765     {
4766       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4767       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4768       if(!cm.isQuadratic())
4769         {
4770           _types.insert(type);
4771           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4772           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4773         }
4774       else
4775         {
4776           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4777           _types.insert(typel);
4778           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4779           int newNbOfNodes=cml.getNumberOfNodes();
4780           if(cml.isDynamic())
4781             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4782           *ocptr++=(int)typel;
4783           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4784           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4785         }
4786     }
4787   setConnectivity(newConn,newConnI,false);
4788 }
4789
4790 /*!
4791  * This method converts all linear cell in \a this to quadratic one.
4792  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4793  * type of cells expected. For example INTERP_KERNEL::NORM_TRI3 can be converted to INTERP_KERNEL::NORM_TRI6 if \a conversionType is equal to 0 (the default)
4794  * or to INTERP_KERNEL::NORM_TRI7 if \a conversionType is equal to 1. All non linear cells and polyhedron in \a this are let untouched.
4795  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4796  * end of the existing coordinates.
4797  * 
4798  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4799  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4800  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4801  * 
4802  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4803  *
4804  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4805  */
4806 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4807 {
4808   DataArrayInt *conn=0,*connI=0;
4809   DataArrayDouble *coords=0;
4810   std::set<INTERP_KERNEL::NormalizedCellType> types;
4811   checkFullyDefined();
4812   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4813   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4814   int meshDim=getMeshDimension();
4815   switch(conversionType)
4816     {
4817     case 0:
4818       switch(meshDim)
4819         {
4820         case 1:
4821           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4822           connSafe=conn; connISafe=connI; coordsSafe=coords;
4823           break;
4824         case 2:
4825           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4826           connSafe=conn; connISafe=connI; coordsSafe=coords;
4827           break;
4828         case 3:
4829           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4830           connSafe=conn; connISafe=connI; coordsSafe=coords;
4831           break;
4832         default:
4833           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4834         }
4835       break;
4836     case 1:
4837       {
4838         switch(meshDim)
4839         {
4840         case 1:
4841           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4842           connSafe=conn; connISafe=connI; coordsSafe=coords;
4843           break;
4844         case 2:
4845           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4846           connSafe=conn; connISafe=connI; coordsSafe=coords;
4847           break;
4848         case 3:
4849           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4850           connSafe=conn; connISafe=connI; coordsSafe=coords;
4851           break;
4852         default:
4853           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4854         }
4855         break;
4856       }
4857     default:
4858       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4859     }
4860   setConnectivity(connSafe,connISafe,false);
4861   _types=types;
4862   setCoords(coordsSafe);
4863   return ret.retn();
4864 }
4865
4866 /*!
4867  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4868  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4869  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4870  */
4871 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4872 {
4873   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4874   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4875   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4876   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4877   int nbOfCells=getNumberOfCells();
4878   int nbOfNodes=getNumberOfNodes();
4879   const int *cPtr=_nodal_connec->getConstPointer();
4880   const int *icPtr=_nodal_connec_index->getConstPointer();
4881   int lastVal=0,offset=nbOfNodes;
4882   for(int i=0;i<nbOfCells;i++,icPtr++)
4883     {
4884       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4885       if(type==INTERP_KERNEL::NORM_SEG2)
4886         {
4887           types.insert(INTERP_KERNEL::NORM_SEG3);
4888           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4889           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4890           newConn->pushBackSilent(offset++);
4891           lastVal+=4;
4892           newConnI->pushBackSilent(lastVal);
4893           ret->pushBackSilent(i);
4894         }
4895       else
4896         {
4897           types.insert(type);
4898           lastVal+=(icPtr[1]-icPtr[0]);
4899           newConnI->pushBackSilent(lastVal);
4900           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4901         }
4902     }
4903   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4904   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4905   return ret.retn();
4906 }
4907
4908 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2DAnd3D0(const MEDCouplingUMesh *m1D, const DataArrayInt *desc, const DataArrayInt *descI, DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4909 {
4910   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4911   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4912   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4913   //
4914   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4915   DataArrayInt *conn1D=0,*conn1DI=0;
4916   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4917   DataArrayDouble *coordsTmp=0;
4918   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4919   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4920   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4921   const int *c1DPtr=conn1D->begin();
4922   const int *c1DIPtr=conn1DI->begin();
4923   int nbOfCells=getNumberOfCells();
4924   const int *cPtr=_nodal_connec->getConstPointer();
4925   const int *icPtr=_nodal_connec_index->getConstPointer();
4926   int lastVal=0;
4927   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4928     {
4929       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4930       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4931       if(!cm.isQuadratic())
4932         {
4933           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4934           types.insert(typ2); newConn->pushBackSilent(typ2);
4935           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4936           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4937             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4938           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4939           newConnI->pushBackSilent(lastVal);
4940           ret->pushBackSilent(i);
4941         }
4942       else
4943         {
4944           types.insert(typ);
4945           lastVal+=(icPtr[1]-icPtr[0]);
4946           newConnI->pushBackSilent(lastVal);
4947           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4948         }
4949     }
4950   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4951   return ret.retn();
4952 }
4953
4954 /*!
4955  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4956  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4957  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4958  */
4959 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4960 {
4961   
4962   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4963   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4964   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4965 }
4966
4967 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4968 {
4969   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4970   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4971   //
4972   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4973   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4974   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4975   //
4976   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4977   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4978   DataArrayInt *conn1D=0,*conn1DI=0;
4979   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4980   DataArrayDouble *coordsTmp=0;
4981   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4982   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4984   const int *c1DPtr=conn1D->begin();
4985   const int *c1DIPtr=conn1DI->begin();
4986   int nbOfCells=getNumberOfCells();
4987   const int *cPtr=_nodal_connec->getConstPointer();
4988   const int *icPtr=_nodal_connec_index->getConstPointer();
4989   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4990   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4991     {
4992       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4993       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4994       if(!cm.isQuadratic())
4995         {
4996           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4997           types.insert(typ2); newConn->pushBackSilent(typ2);
4998           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4999           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5000             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5001           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5002           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5003           newConnI->pushBackSilent(lastVal);
5004           ret->pushBackSilent(i);
5005         }
5006       else
5007         {
5008           types.insert(typ);
5009           lastVal+=(icPtr[1]-icPtr[0]);
5010           newConnI->pushBackSilent(lastVal);
5011           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5012         }
5013     }
5014   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5015   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5016   return ret.retn();
5017 }
5018
5019 /*!
5020  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5021  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5022  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5023  */
5024 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5025 {
5026   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5027   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5028   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5029 }
5030
5031 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5032 {
5033   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5034   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5035   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5036   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5037   //
5038   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5039   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5040   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5041   //
5042   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5043   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5044   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5045   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5046   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5047   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5048   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5049   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5050   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5051   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5052   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5053   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5054   int nbOfCells=getNumberOfCells();
5055   const int *cPtr=_nodal_connec->getConstPointer();
5056   const int *icPtr=_nodal_connec_index->getConstPointer();
5057   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5058   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5059     {
5060       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5061       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5062       if(!cm.isQuadratic())
5063         {
5064           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5065           if(typ2==INTERP_KERNEL::NORM_ERROR)
5066             {
5067               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5068               throw INTERP_KERNEL::Exception(oss.str().c_str());
5069             }
5070           types.insert(typ2); newConn->pushBackSilent(typ2);
5071           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5072           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5073             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5074           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5075             {
5076               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5077               int tmpPos=newConn->getNumberOfTuples();
5078               newConn->pushBackSilent(nodeId2);
5079               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5080             }
5081           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5082           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5083           newConnI->pushBackSilent(lastVal);
5084           ret->pushBackSilent(i);
5085         }
5086       else
5087         {
5088           types.insert(typ);
5089           lastVal+=(icPtr[1]-icPtr[0]);
5090           newConnI->pushBackSilent(lastVal);
5091           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5092         }
5093     }
5094   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5095   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5096   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5097   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5098   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5099   int *c=newConn->getPointer();
5100   const int *cI(newConnI->begin());
5101   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5102     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5103   offset=coordsTmp2Safe->getNumberOfTuples();
5104   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5105     c[cI[(*elt)+1]-1]+=offset;
5106   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5107   return ret.retn();
5108 }
5109
5110 /*!
5111  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5112  * so that the number of cells remains the same. Quadratic faces are converted to
5113  * polygons. This method works only for 2D meshes in
5114  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5115  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5116  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5117  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5118  *         a polylinized edge constituting the input polygon.
5119  *  \throw If the coordinates array is not set.
5120  *  \throw If the nodal connectivity of cells is not defined.
5121  *  \throw If \a this->getMeshDimension() != 2.
5122  *  \throw If \a this->getSpaceDimension() != 2.
5123  */
5124 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5125 {
5126   checkFullyDefined();
5127   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5128     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5129   double epsa=fabs(eps);
5130   if(epsa<std::numeric_limits<double>::min())
5131     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5132   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5133   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5134   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5135   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5136   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5137   revDesc1=0; revDescIndx1=0;
5138   mDesc->tessellate2DCurve(eps);
5139   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5140   setCoords(mDesc->getCoords());
5141 }
5142
5143 /*!
5144  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5145  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5146  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5147  *         a sub-divided edge.
5148  *  \throw If the coordinates array is not set.
5149  *  \throw If the nodal connectivity of cells is not defined.
5150  *  \throw If \a this->getMeshDimension() != 1.
5151  *  \throw If \a this->getSpaceDimension() != 2.
5152  */
5153 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5154 {
5155   checkFullyDefined();
5156   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5157     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5158   double epsa=fabs(eps);
5159   if(epsa<std::numeric_limits<double>::min())
5160     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5161   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5162   int nbCells=getNumberOfCells();
5163   int nbNodes=getNumberOfNodes();
5164   const int *conn=_nodal_connec->getConstPointer();
5165   const int *connI=_nodal_connec_index->getConstPointer();
5166   const double *coords=_coords->getConstPointer();
5167   std::vector<double> addCoo;
5168   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5169   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5170   newConnI->alloc(nbCells+1,1);
5171   int *newConnIPtr=newConnI->getPointer();
5172   *newConnIPtr=0;
5173   int tmp1[3];
5174   INTERP_KERNEL::Node *tmp2[3];
5175   std::set<INTERP_KERNEL::NormalizedCellType> types;
5176   for(int i=0;i<nbCells;i++,newConnIPtr++)
5177     {
5178       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5179       if(cm.isQuadratic())
5180         {//assert(connI[i+1]-connI[i]-1==3)
5181           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5182           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5183           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5184           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5185           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5186           if(eac)
5187             {
5188               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5189               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5190               delete eac;
5191               newConnIPtr[1]=(int)newConn.size();
5192             }
5193           else
5194             {
5195               types.insert(INTERP_KERNEL::NORM_SEG2);
5196               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5197               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5198               newConnIPtr[1]=newConnIPtr[0]+3;
5199             }
5200         }
5201       else
5202         {
5203           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5204           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5205           newConnIPtr[1]=newConnIPtr[0]+3;
5206         }
5207     }
5208   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5209     return ;
5210   _types=types;
5211   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5212   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5213   newConnArr->alloc((int)newConn.size(),1);
5214   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5215   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5216   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5217   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5218   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5219   std::copy(addCoo.begin(),addCoo.end(),work);
5220   DataArrayDouble::SetArrayIn(newCoords,_coords);
5221   updateTime();
5222 }
5223
5224 /*!
5225  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5226  * In addition, returns an array mapping new cells to old ones. <br>
5227  * This method typically increases the number of cells in \a this mesh
5228  * but the number of nodes remains \b unchanged.
5229  * That's why the 3D splitting policies
5230  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5231  *  \param [in] policy - specifies a pattern used for splitting.
5232  * The semantic of \a policy is:
5233  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5234  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5235  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5236  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5237  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5238  *          an id of old cell producing it. The caller is to delete this array using
5239  *         decrRef() as it is no more needed. 
5240  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5241  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5242  *          and \a this->getMeshDimension() != 3. 
5243  *  \throw If \a policy is not one of the four discussed above.
5244  *  \throw If the nodal connectivity of cells is not defined.
5245  */
5246 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5247 {
5248   switch(policy)
5249     {
5250     case 0:
5251       return simplexizePol0();
5252     case 1:
5253       return simplexizePol1();
5254     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5255       return simplexizePlanarFace5();
5256     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5257       return simplexizePlanarFace6();
5258     default:
5259       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexize : unrecognized policy ! Must be :\n  - 0 or 1 (only available for meshdim=2) \n  - PLANAR_FACE_5, PLANAR_FACE_6  (only for meshdim=3)");
5260     }
5261 }
5262
5263 /*!
5264  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5265  * - 1D: INTERP_KERNEL::NORM_SEG2
5266  * - 2D: INTERP_KERNEL::NORM_TRI3
5267  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5268  *
5269  * This method is useful for users that need to use P1 field services as
5270  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5271  * All these methods need mesh support containing only simplex cells.
5272  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5273  *  \throw If the coordinates array is not set.
5274  *  \throw If the nodal connectivity of cells is not defined.
5275  *  \throw If \a this->getMeshDimension() < 1.
5276  */
5277 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5278 {
5279   checkFullyDefined();
5280   int mdim=getMeshDimension();
5281   if(mdim<1 || mdim>3)
5282     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5283   int nbCells=getNumberOfCells();
5284   const int *conn=_nodal_connec->getConstPointer();
5285   const int *connI=_nodal_connec_index->getConstPointer();
5286   for(int i=0;i<nbCells;i++)
5287     {
5288       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5289       if(!cm.isSimplex())
5290         return false;
5291     }
5292   return true;
5293 }
5294
5295 /*!
5296  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5297  */
5298 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5299 {
5300   checkConnectivityFullyDefined();
5301   if(getMeshDimension()!=2)
5302     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5303   int nbOfCells=getNumberOfCells();
5304   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5305   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5306   ret->alloc(nbOfCells+nbOfCutCells,1);
5307   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5308   int *retPt=ret->getPointer();
5309   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5310   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5311   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5312   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5313   int *pt=newConn->getPointer();
5314   int *ptI=newConnI->getPointer();
5315   ptI[0]=0;
5316   const int *oldc=_nodal_connec->getConstPointer();
5317   const int *ci=_nodal_connec_index->getConstPointer();
5318   for(int i=0;i<nbOfCells;i++,ci++)
5319     {
5320       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5321         {
5322           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5323                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5324           pt=std::copy(tmp,tmp+8,pt);
5325           ptI[1]=ptI[0]+4;
5326           ptI[2]=ptI[0]+8;
5327           *retPt++=i;
5328           *retPt++=i;
5329           ptI+=2;
5330         }
5331       else
5332         {
5333           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5334           ptI[1]=ptI[0]+ci[1]-ci[0];
5335           ptI++;
5336           *retPt++=i;
5337         }
5338     }
5339   _nodal_connec->decrRef();
5340   _nodal_connec=newConn.retn();
5341   _nodal_connec_index->decrRef();
5342   _nodal_connec_index=newConnI.retn();
5343   computeTypes();
5344   updateTime();
5345   return ret.retn();
5346 }
5347
5348 /*!
5349  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5350  */
5351 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5352 {
5353   checkConnectivityFullyDefined();
5354   if(getMeshDimension()!=2)
5355     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5356   int nbOfCells=getNumberOfCells();
5357   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5358   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5359   ret->alloc(nbOfCells+nbOfCutCells,1);
5360   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5361   int *retPt=ret->getPointer();
5362   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5363   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5364   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5365   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5366   int *pt=newConn->getPointer();
5367   int *ptI=newConnI->getPointer();
5368   ptI[0]=0;
5369   const int *oldc=_nodal_connec->getConstPointer();
5370   const int *ci=_nodal_connec_index->getConstPointer();
5371   for(int i=0;i<nbOfCells;i++,ci++)
5372     {
5373       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5374         {
5375           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5376                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5377           pt=std::copy(tmp,tmp+8,pt);
5378           ptI[1]=ptI[0]+4;
5379           ptI[2]=ptI[0]+8;
5380           *retPt++=i;
5381           *retPt++=i;
5382           ptI+=2;
5383         }
5384       else
5385         {
5386           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5387           ptI[1]=ptI[0]+ci[1]-ci[0];
5388           ptI++;
5389           *retPt++=i;
5390         }
5391     }
5392   _nodal_connec->decrRef();
5393   _nodal_connec=newConn.retn();
5394   _nodal_connec_index->decrRef();
5395   _nodal_connec_index=newConnI.retn();
5396   computeTypes();
5397   updateTime();
5398   return ret.retn();
5399 }
5400
5401 /*!
5402  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5403  */
5404 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5405 {
5406   checkConnectivityFullyDefined();
5407   if(getMeshDimension()!=3)
5408     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5409   int nbOfCells=getNumberOfCells();
5410   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5411   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5412   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5413   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5414   int *retPt=ret->getPointer();
5415   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5416   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5417   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5418   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5419   int *pt=newConn->getPointer();
5420   int *ptI=newConnI->getPointer();
5421   ptI[0]=0;
5422   const int *oldc=_nodal_connec->getConstPointer();
5423   const int *ci=_nodal_connec_index->getConstPointer();
5424   for(int i=0;i<nbOfCells;i++,ci++)
5425     {
5426       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5427         {
5428           for(int j=0;j<5;j++,pt+=5,ptI++)
5429             {
5430               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5431               pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+3]+1];
5432               *retPt++=i;
5433               ptI[1]=ptI[0]+5;
5434             }
5435         }
5436       else
5437         {
5438           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5439           ptI[1]=ptI[0]+ci[1]-ci[0];
5440           ptI++;
5441           *retPt++=i;
5442         }
5443     }
5444   _nodal_connec->decrRef();
5445   _nodal_connec=newConn.retn();
5446   _nodal_connec_index->decrRef();
5447   _nodal_connec_index=newConnI.retn();
5448   computeTypes();
5449   updateTime();
5450   return ret.retn();
5451 }
5452
5453 /*!
5454  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5455  */
5456 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5457 {
5458   checkConnectivityFullyDefined();
5459   if(getMeshDimension()!=3)
5460     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5461   int nbOfCells=getNumberOfCells();
5462   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5463   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5464   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5465   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5466   int *retPt=ret->getPointer();
5467   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5468   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5469   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5470   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5471   int *pt=newConn->getPointer();
5472   int *ptI=newConnI->getPointer();
5473   ptI[0]=0;
5474   const int *oldc=_nodal_connec->getConstPointer();
5475   const int *ci=_nodal_connec_index->getConstPointer();
5476   for(int i=0;i<nbOfCells;i++,ci++)
5477     {
5478       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5479         {
5480           for(int j=0;j<6;j++,pt+=5,ptI++)
5481             {
5482               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5483               pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+3]+1];
5484               *retPt++=i;
5485               ptI[1]=ptI[0]+5;
5486             }
5487         }
5488       else
5489         {
5490           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5491           ptI[1]=ptI[0]+ci[1]-ci[0];
5492           ptI++;
5493           *retPt++=i;
5494         }
5495     }
5496   _nodal_connec->decrRef();
5497   _nodal_connec=newConn.retn();
5498   _nodal_connec_index->decrRef();
5499   _nodal_connec_index=newConnI.retn();
5500   computeTypes();
5501   updateTime();
5502   return ret.retn();
5503 }
5504
5505 /*!
5506  * This private method is used to subdivide edges of a mesh with meshdim==2. If \a this has no a meshdim equal to 2 an exception will be thrown.
5507  * This method completly ignore coordinates.
5508  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5509  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5510  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5511  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5512  */
5513 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5514 {
5515   checkFullyDefined();
5516   if(getMeshDimension()!=2)
5517     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5518   int nbOfCells=getNumberOfCells();
5519   int *connI=_nodal_connec_index->getPointer();
5520   int newConnLgth=0;
5521   for(int i=0;i<nbOfCells;i++,connI++)
5522     {
5523       int offset=descIndex[i];
5524       int nbOfEdges=descIndex[i+1]-offset;
5525       //
5526       bool ddirect=desc[offset+nbOfEdges-1]>0;
5527       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5528       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5529       for(int j=0;j<nbOfEdges;j++)
5530         {
5531           bool direct=desc[offset+j]>0;
5532           int edgeId=std::abs(desc[offset+j])-1;
5533           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5534             {
5535               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5536               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5537               int ref2=direct?id1:id2;
5538               if(ref==ref2)
5539                 {
5540                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5541                   newConnLgth+=nbOfSubNodes-1;
5542                   ref=direct?id2:id1;
5543                 }
5544               else
5545                 {
5546                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5547                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5548                 }
5549             }
5550           else
5551             {
5552               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5553             }
5554         }
5555       newConnLgth++;//+1 is for cell type
5556       connI[1]=newConnLgth;
5557     }
5558   //
5559   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5560   newConn->alloc(newConnLgth,1);
5561   int *work=newConn->getPointer();
5562   for(int i=0;i<nbOfCells;i++)
5563     {
5564       *work++=INTERP_KERNEL::NORM_POLYGON;
5565       int offset=descIndex[i];
5566       int nbOfEdges=descIndex[i+1]-offset;
5567       for(int j=0;j<nbOfEdges;j++)
5568         {
5569           bool direct=desc[offset+j]>0;
5570           int edgeId=std::abs(desc[offset+j])-1;
5571           if(direct)
5572             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5573           else
5574             {
5575               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5576               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5577               work=std::copy(it,it+nbOfSubNodes-1,work);
5578             }
5579         }
5580     }
5581   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5582   _types.clear();
5583   if(nbOfCells>0)
5584     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5585 }
5586
5587 /*!
5588  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5589  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5590  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5591  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5592  * so it can be useful to call mergeNodes() before calling this method.
5593  *  \throw If \a this->getMeshDimension() <= 1.
5594  *  \throw If the coordinates array is not set.
5595  *  \throw If the nodal connectivity of cells is not defined.
5596  */
5597 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5598 {
5599   checkFullyDefined();
5600   if(getMeshDimension()<=1)
5601     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5602   int nbOfCells=getNumberOfCells();
5603   if(nbOfCells<1)
5604     return ;
5605   int initMeshLgth=getMeshLength();
5606   int *conn=_nodal_connec->getPointer();
5607   int *index=_nodal_connec_index->getPointer();
5608   int posOfCurCell=0;
5609   int newPos=0;
5610   int lgthOfCurCell;
5611   for(int i=0;i<nbOfCells;i++)
5612     {
5613       lgthOfCurCell=index[i+1]-posOfCurCell;
5614       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5615       int newLgth;
5616       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5617                                                                                                      conn+newPos+1,newLgth);
5618       conn[newPos]=newType;
5619       newPos+=newLgth+1;
5620       posOfCurCell=index[i+1];
5621       index[i+1]=newPos;
5622     }
5623   if(newPos!=initMeshLgth)
5624     _nodal_connec->reAlloc(newPos);
5625   computeTypes();
5626 }
5627
5628 /*!
5629  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5630  * A cell is considered to be oriented correctly if an angle between its
5631  * normal vector and a given vector is less than \c PI / \c 2.
5632  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5633  *         cells. 
5634  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5635  *         checked.
5636  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5637  *         is not cleared before filling in.
5638  *  \throw If \a this->getMeshDimension() != 2.
5639  *  \throw If \a this->getSpaceDimension() != 3.
5640  *
5641  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5642  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5643  */
5644 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5645 {
5646   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5647     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5648   int nbOfCells=getNumberOfCells();
5649   const int *conn=_nodal_connec->getConstPointer();
5650   const int *connI=_nodal_connec_index->getConstPointer();
5651   const double *coordsPtr=_coords->getConstPointer();
5652   for(int i=0;i<nbOfCells;i++)
5653     {
5654       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5655       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5656         {
5657           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5658           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5659             cells.push_back(i);
5660         }
5661     }
5662 }
5663
5664 /*!
5665  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5666  * considered to be oriented correctly if an angle between its normal vector and a
5667  * given vector is less than \c PI / \c 2. 
5668  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5669  *         cells. 
5670  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5671  *         checked.
5672  *  \throw If \a this->getMeshDimension() != 2.
5673  *  \throw If \a this->getSpaceDimension() != 3.
5674  *
5675  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5676  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5677  */
5678 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5679 {
5680   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5681     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5682   int nbOfCells=getNumberOfCells();
5683   int *conn=_nodal_connec->getPointer();
5684   const int *connI=_nodal_connec_index->getConstPointer();
5685   const double *coordsPtr=_coords->getConstPointer();
5686   bool isModified=false;
5687   for(int i=0;i<nbOfCells;i++)
5688     {
5689       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5690       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5691         {
5692           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5693           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5694             {
5695               isModified=true;
5696               std::vector<int> tmp(connI[i+1]-connI[i]-2);
5697               std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5698               std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5699             }
5700         }
5701     }
5702   if(isModified)
5703     _nodal_connec->declareAsNew();
5704   updateTime();
5705 }
5706
5707 /*!
5708  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5709  * oriented facets. The normal vector of the facet should point out of the cell.
5710  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5711  *         is not cleared before filling in.
5712  *  \throw If \a this->getMeshDimension() != 3.
5713  *  \throw If \a this->getSpaceDimension() != 3.
5714  *  \throw If the coordinates array is not set.
5715  *  \throw If the nodal connectivity of cells is not defined.
5716  *
5717  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5718  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5719  */
5720 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5721 {
5722   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5723     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5724   int nbOfCells=getNumberOfCells();
5725   const int *conn=_nodal_connec->getConstPointer();
5726   const int *connI=_nodal_connec_index->getConstPointer();
5727   const double *coordsPtr=_coords->getConstPointer();
5728   for(int i=0;i<nbOfCells;i++)
5729     {
5730       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5731       if(type==INTERP_KERNEL::NORM_POLYHED)
5732         {
5733           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5734             cells.push_back(i);
5735         }
5736     }
5737 }
5738
5739 /*!
5740  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5741  * out of the cell. 
5742  *  \throw If \a this->getMeshDimension() != 3.
5743  *  \throw If \a this->getSpaceDimension() != 3.
5744  *  \throw If the coordinates array is not set.
5745  *  \throw If the nodal connectivity of cells is not defined.
5746  *  \throw If the reparation fails.
5747  *
5748  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5749  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5750  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5751  */
5752 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5753 {
5754   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5755     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5756   int nbOfCells=getNumberOfCells();
5757   int *conn=_nodal_connec->getPointer();
5758   const int *connI=_nodal_connec_index->getConstPointer();
5759   const double *coordsPtr=_coords->getConstPointer();
5760   for(int i=0;i<nbOfCells;i++)
5761     {
5762       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5763       if(type==INTERP_KERNEL::NORM_POLYHED)
5764         {
5765           try
5766             {
5767               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5768                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5769             }
5770           catch(INTERP_KERNEL::Exception& e)
5771             {
5772               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5773               throw INTERP_KERNEL::Exception(oss.str().c_str());
5774             }
5775         }
5776     }
5777   updateTime();
5778 }
5779
5780 /*!
5781  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5782  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5783  * according to which the first facet of the cell should be oriented to have the normal vector
5784  * pointing out of cell.
5785  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5786  *         cells. The caller is to delete this array using decrRef() as it is no more
5787  *         needed. 
5788  *  \throw If \a this->getMeshDimension() != 3.
5789  *  \throw If \a this->getSpaceDimension() != 3.
5790  *  \throw If the coordinates array is not set.
5791  *  \throw If the nodal connectivity of cells is not defined.
5792  *
5793  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5794  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5795  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5796  */
5797 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5798 {
5799   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5800   if(getMeshDimension()!=3)
5801     throw INTERP_KERNEL::Exception(msg);
5802   int spaceDim=getSpaceDimension();
5803   if(spaceDim!=3)
5804     throw INTERP_KERNEL::Exception(msg);
5805   //
5806   int nbOfCells=getNumberOfCells();
5807   int *conn=_nodal_connec->getPointer();
5808   const int *connI=_nodal_connec_index->getConstPointer();
5809   const double *coo=getCoords()->getConstPointer();
5810   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5811   for(int i=0;i<nbOfCells;i++)
5812     {
5813       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5814       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5815         {
5816           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5817             {
5818               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5819               cells->pushBackSilent(i);
5820             }
5821         }
5822     }
5823   return cells.retn();
5824 }
5825
5826 /*!
5827  * This method is a faster method to correct orientation of all 3D cells in \a this.
5828  * This method works only if \a this is a 3D mesh, that is to say a mesh with mesh dimension 3 and a space dimension 3.
5829  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5830  * 
5831  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5832  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5833  */
5834 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5835 {
5836   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5837     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5838   int nbOfCells=getNumberOfCells();
5839   int *conn=_nodal_connec->getPointer();
5840   const int *connI=_nodal_connec_index->getConstPointer();
5841   const double *coordsPtr=_coords->getConstPointer();
5842   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5843   for(int i=0;i<nbOfCells;i++)
5844     {
5845       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5846       switch(type)
5847         {
5848         case INTERP_KERNEL::NORM_TETRA4:
5849           {
5850             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5851               {
5852                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5853                 ret->pushBackSilent(i);
5854               }
5855             break;
5856           }
5857         case INTERP_KERNEL::NORM_PYRA5:
5858           {
5859             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5860               {
5861                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5862                 ret->pushBackSilent(i);
5863               }
5864             break;
5865           }
5866         case INTERP_KERNEL::NORM_PENTA6:
5867         case INTERP_KERNEL::NORM_HEXA8:
5868         case INTERP_KERNEL::NORM_HEXGP12:
5869           {
5870             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5871               {
5872                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5873                 ret->pushBackSilent(i);
5874               }
5875             break;
5876           }
5877         case INTERP_KERNEL::NORM_POLYHED:
5878           {
5879             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5880               {
5881                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5882                 ret->pushBackSilent(i);
5883               }
5884             break;
5885           }
5886         default:
5887           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orientCorrectly3DCells : Your mesh contains type of cell not supported yet ! send mail to anthony.geay@cea.fr to add it !");
5888         }
5889     }
5890   updateTime();
5891   return ret.retn();
5892 }
5893
5894 /*!
5895  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5896  * If it is not the case an exception will be thrown.
5897  * This method is fast because the first cell of \a this is used to compute the plane.
5898  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5899  * \param pos output of size at least 3 used to store a point owned of searched plane.
5900  */
5901 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5902 {
5903   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5904     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5905   const int *conn=_nodal_connec->getConstPointer();
5906   const int *connI=_nodal_connec_index->getConstPointer();
5907   const double *coordsPtr=_coords->getConstPointer();
5908   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5909   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5910 }
5911
5912 /*!
5913  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5914  * cells. Currently cells of the following types are treated:
5915  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5916  * For a cell of other type an exception is thrown.
5917  * Space dimension of a 2D mesh can be either 2 or 3.
5918  * The Edge Ratio of a cell \f$t\f$ is: 
5919  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5920  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5921  *  the smallest edge lengths of \f$t\f$.
5922  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5923  *          cells and one time, lying on \a this mesh. The caller is to delete this
5924  *          field using decrRef() as it is no more needed. 
5925  *  \throw If the coordinates array is not set.
5926  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5927  *  \throw If the connectivity data array has more than one component.
5928  *  \throw If the connectivity data array has a named component.
5929  *  \throw If the connectivity index data array has more than one component.
5930  *  \throw If the connectivity index data array has a named component.
5931  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5932  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5933  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5934  */
5935 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5936 {
5937   checkCoherency();
5938   int spaceDim=getSpaceDimension();
5939   int meshDim=getMeshDimension();
5940   if(spaceDim!=2 && spaceDim!=3)
5941     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5942   if(meshDim!=2 && meshDim!=3)
5943     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5944   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5945   ret->setMesh(this);
5946   int nbOfCells=getNumberOfCells();
5947   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5948   arr->alloc(nbOfCells,1);
5949   double *pt=arr->getPointer();
5950   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5951   const int *conn=_nodal_connec->getConstPointer();
5952   const int *connI=_nodal_connec_index->getConstPointer();
5953   const double *coo=_coords->getConstPointer();
5954   double tmp[12];
5955   for(int i=0;i<nbOfCells;i++,pt++)
5956     {
5957       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5958       switch(t)
5959         {
5960           case INTERP_KERNEL::NORM_TRI3:
5961             {
5962               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5963               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5964               break;
5965             }
5966           case INTERP_KERNEL::NORM_QUAD4:
5967             {
5968               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5969               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5970               break;
5971             }
5972           case INTERP_KERNEL::NORM_TETRA4:
5973             {
5974               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5975               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5976               break;
5977             }
5978         default:
5979           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5980         }
5981       conn+=connI[i+1]-connI[i];
5982     }
5983   ret->setName("EdgeRatio");
5984   ret->synchronizeTimeWithSupport();
5985   return ret.retn();
5986 }
5987
5988 /*!
5989  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5990  * cells. Currently cells of the following types are treated:
5991  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5992  * For a cell of other type an exception is thrown.
5993  * Space dimension of a 2D mesh can be either 2 or 3.
5994  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5995  *          cells and one time, lying on \a this mesh. The caller is to delete this
5996  *          field using decrRef() as it is no more needed. 
5997  *  \throw If the coordinates array is not set.
5998  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5999  *  \throw If the connectivity data array has more than one component.
6000  *  \throw If the connectivity data array has a named component.
6001  *  \throw If the connectivity index data array has more than one component.
6002  *  \throw If the connectivity index data array has a named component.
6003  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6004  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6005  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6006  */
6007 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6008 {
6009   checkCoherency();
6010   int spaceDim=getSpaceDimension();
6011   int meshDim=getMeshDimension();
6012   if(spaceDim!=2 && spaceDim!=3)
6013     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6014   if(meshDim!=2 && meshDim!=3)
6015     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6016   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6017   ret->setMesh(this);
6018   int nbOfCells=getNumberOfCells();
6019   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6020   arr->alloc(nbOfCells,1);
6021   double *pt=arr->getPointer();
6022   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6023   const int *conn=_nodal_connec->getConstPointer();
6024   const int *connI=_nodal_connec_index->getConstPointer();
6025   const double *coo=_coords->getConstPointer();
6026   double tmp[12];
6027   for(int i=0;i<nbOfCells;i++,pt++)
6028     {
6029       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6030       switch(t)
6031         {
6032           case INTERP_KERNEL::NORM_TRI3:
6033             {
6034               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6035               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6036               break;
6037             }
6038           case INTERP_KERNEL::NORM_QUAD4:
6039             {
6040               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6041               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6042               break;
6043             }
6044           case INTERP_KERNEL::NORM_TETRA4:
6045             {
6046               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6047               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6048               break;
6049             }
6050         default:
6051           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6052         }
6053       conn+=connI[i+1]-connI[i];
6054     }
6055   ret->setName("AspectRatio");
6056   ret->synchronizeTimeWithSupport();
6057   return ret.retn();
6058 }
6059
6060 /*!
6061  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6062  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6063  * treated: INTERP_KERNEL::NORM_QUAD4.
6064  * For a cell of other type an exception is thrown.
6065  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6066  *          cells and one time, lying on \a this mesh. The caller is to delete this
6067  *          field using decrRef() as it is no more needed. 
6068  *  \throw If the coordinates array is not set.
6069  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6070  *  \throw If the connectivity data array has more than one component.
6071  *  \throw If the connectivity data array has a named component.
6072  *  \throw If the connectivity index data array has more than one component.
6073  *  \throw If the connectivity index data array has a named component.
6074  *  \throw If \a this->getMeshDimension() != 2.
6075  *  \throw If \a this->getSpaceDimension() != 3.
6076  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6077  */
6078 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6079 {
6080   checkCoherency();
6081   int spaceDim=getSpaceDimension();
6082   int meshDim=getMeshDimension();
6083   if(spaceDim!=3)
6084     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6085   if(meshDim!=2)
6086     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6087   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6088   ret->setMesh(this);
6089   int nbOfCells=getNumberOfCells();
6090   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6091   arr->alloc(nbOfCells,1);
6092   double *pt=arr->getPointer();
6093   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6094   const int *conn=_nodal_connec->getConstPointer();
6095   const int *connI=_nodal_connec_index->getConstPointer();
6096   const double *coo=_coords->getConstPointer();
6097   double tmp[12];
6098   for(int i=0;i<nbOfCells;i++,pt++)
6099     {
6100       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6101       switch(t)
6102         {
6103           case INTERP_KERNEL::NORM_QUAD4:
6104             {
6105               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6106               *pt=INTERP_KERNEL::quadWarp(tmp);
6107               break;
6108             }
6109         default:
6110           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6111         }
6112       conn+=connI[i+1]-connI[i];
6113     }
6114   ret->setName("Warp");
6115   ret->synchronizeTimeWithSupport();
6116   return ret.retn();
6117 }
6118
6119
6120 /*!
6121  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6122  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6123  * treated: INTERP_KERNEL::NORM_QUAD4.
6124  * For a cell of other type an exception is thrown.
6125  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6126  *          cells and one time, lying on \a this mesh. The caller is to delete this
6127  *          field using decrRef() as it is no more needed. 
6128  *  \throw If the coordinates array is not set.
6129  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6130  *  \throw If the connectivity data array has more than one component.
6131  *  \throw If the connectivity data array has a named component.
6132  *  \throw If the connectivity index data array has more than one component.
6133  *  \throw If the connectivity index data array has a named component.
6134  *  \throw If \a this->getMeshDimension() != 2.
6135  *  \throw If \a this->getSpaceDimension() != 3.
6136  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6137  */
6138 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6139 {
6140   checkCoherency();
6141   int spaceDim=getSpaceDimension();
6142   int meshDim=getMeshDimension();
6143   if(spaceDim!=3)
6144     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6145   if(meshDim!=2)
6146     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6147   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6148   ret->setMesh(this);
6149   int nbOfCells=getNumberOfCells();
6150   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6151   arr->alloc(nbOfCells,1);
6152   double *pt=arr->getPointer();
6153   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6154   const int *conn=_nodal_connec->getConstPointer();
6155   const int *connI=_nodal_connec_index->getConstPointer();
6156   const double *coo=_coords->getConstPointer();
6157   double tmp[12];
6158   for(int i=0;i<nbOfCells;i++,pt++)
6159     {
6160       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6161       switch(t)
6162         {
6163           case INTERP_KERNEL::NORM_QUAD4:
6164             {
6165               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6166               *pt=INTERP_KERNEL::quadSkew(tmp);
6167               break;
6168             }
6169         default:
6170           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6171         }
6172       conn+=connI[i+1]-connI[i];
6173     }
6174   ret->setName("Skew");
6175   ret->synchronizeTimeWithSupport();
6176   return ret.retn();
6177 }
6178
6179 /*!
6180  * This method aggregate the bbox of each cell and put it into bbox parameter.
6181  * \param bbox out parameter of size 2*spacedim*nbOfcells.
6182  */
6183 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6184 {
6185   int spaceDim=getSpaceDimension();
6186   int nbOfCells=getNumberOfCells();
6187   bbox.resize(2*nbOfCells*spaceDim);
6188   for(int i=0;i<nbOfCells*spaceDim;i++)
6189     {
6190       bbox[2*i]=std::numeric_limits<double>::max();
6191       bbox[2*i+1]=-std::numeric_limits<double>::max();
6192     }
6193   const double *coordsPtr=_coords->getConstPointer();
6194   const int *conn=_nodal_connec->getConstPointer();
6195   const int *connI=_nodal_connec_index->getConstPointer();
6196   for(int i=0;i<nbOfCells;i++)
6197     {
6198       int offset=connI[i]+1;
6199       int nbOfNodesForCell=connI[i+1]-offset;
6200       for(int j=0;j<nbOfNodesForCell;j++)
6201         {
6202           int nodeId=conn[offset+j];
6203           if(nodeId>=0)
6204             for(int k=0;k<spaceDim;k++)
6205               {
6206                 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6207                 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6208               }
6209         }
6210     }
6211 }
6212
6213 /// @cond INTERNAL
6214
6215 namespace ParaMEDMEMImpl
6216 {
6217   class ConnReader
6218   {
6219   public:
6220     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6221     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6222   private:
6223     const int *_conn;
6224     int _val;
6225   };
6226
6227   class ConnReader2
6228   {
6229   public:
6230     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6231     bool operator() (const int& pos) { return _conn[pos]==_val; }
6232   private:
6233     const int *_conn;
6234     int _val;
6235   };
6236 }
6237
6238 /// @endcond
6239
6240 /*!
6241  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6242  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6243  * \a this is composed in cell types.
6244  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6245  * For every k in [0,n] ret[3*k+2]==0 because it has no sense here. 
6246  * This parameter is kept only for compatibility with other methode listed above.
6247  */
6248 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6249 {
6250   checkConnectivityFullyDefined();
6251   const int *conn=_nodal_connec->getConstPointer();
6252   const int *connI=_nodal_connec_index->getConstPointer();
6253   const int *work=connI;
6254   int nbOfCells=getNumberOfCells();
6255   std::size_t n=getAllTypes().size();
6256   std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
6257   std::set<INTERP_KERNEL::NormalizedCellType> types;
6258   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6259     {
6260       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6261       if(types.find(typ)!=types.end())
6262         {
6263           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6264           oss << " is not contiguous !";
6265           throw INTERP_KERNEL::Exception(oss.str().c_str());
6266         }
6267       types.insert(typ);
6268       ret[3*i]=typ;
6269       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6270       ret[3*i+1]=(int)std::distance(work,work2);
6271       work=work2;
6272     }
6273   return ret;
6274 }
6275
6276 /*!
6277  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6278  * only for types cell, type node is not managed.
6279  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6280  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6281  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6282  * If 2 or more same geometric type is in \a code and exception is thrown too.
6283  *
6284  * This method firstly checks
6285  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6286  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6287  * an exception is thrown too.
6288  * 
6289  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6290  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6291  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6292  */
6293 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6294 {
6295   if(code.empty())
6296     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6297   std::size_t sz=code.size();
6298   std::size_t n=sz/3;
6299   if(sz%3!=0)
6300     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6301   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6302   int nb=0;
6303   bool isNoPflUsed=true;
6304   for(std::size_t i=0;i<n;i++)
6305     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6306       {
6307         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6308         nb+=code[3*i+1];
6309         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6310           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6311         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6312       }
6313   if(types.size()!=n)
6314     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6315   if(isNoPflUsed)
6316     {
6317       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6318         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6319       if(types.size()==_types.size())
6320         return 0;
6321     }
6322   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6323   ret->alloc(nb,1);
6324   int *retPtr=ret->getPointer();
6325   const int *connI=_nodal_connec_index->getConstPointer();
6326   const int *conn=_nodal_connec->getConstPointer();
6327   int nbOfCells=getNumberOfCells();
6328   const int *i=connI;
6329   int kk=0;
6330   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6331     {
6332       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6333       int offset=(int)std::distance(connI,i);
6334       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6335       int nbOfCellsOfCurType=(int)std::distance(i,j);
6336       if(code[3*kk+2]==-1)
6337         for(int k=0;k<nbOfCellsOfCurType;k++)
6338           *retPtr++=k+offset;
6339       else
6340         {
6341           int idInIdsPerType=code[3*kk+2];
6342           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6343             {
6344               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6345               if(zePfl)
6346                 {
6347                   zePfl->checkAllocated();
6348                   if(zePfl->getNumberOfComponents()==1)
6349                     {
6350                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6351                         {
6352                           if(*k>=0 && *k<nbOfCellsOfCurType)
6353                             *retPtr=(*k)+offset;
6354                           else
6355                             {
6356                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6357                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6358                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6359                             }
6360                         }
6361                     }
6362                   else
6363                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6364                 }
6365               else
6366                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6367             }
6368           else
6369             {
6370               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6371               oss << " should be in [0," << idsPerType.size() << ") !";
6372               throw INTERP_KERNEL::Exception(oss.str().c_str());
6373             }
6374         }
6375       i=j;
6376     }
6377   return ret.retn();
6378 }
6379
6380 /*!
6381  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6382  * 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.
6383  * 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.
6384  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6385  * 
6386  * \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.
6387  * \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,
6388  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6389  * \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.
6390  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6391  * \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
6392  */
6393 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6394 {
6395   if(!profile)
6396     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6397   if(profile->getNumberOfComponents()!=1)
6398     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6399   checkConnectivityFullyDefined();
6400   const int *conn=_nodal_connec->getConstPointer();
6401   const int *connI=_nodal_connec_index->getConstPointer();
6402   int nbOfCells=getNumberOfCells();
6403   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6404   std::vector<int> typeRangeVals(1);
6405   for(const int *i=connI;i!=connI+nbOfCells;)
6406     {
6407       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6408       if(std::find(types.begin(),types.end(),curType)!=types.end())
6409         {
6410           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6411         }
6412       types.push_back(curType);
6413       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6414       typeRangeVals.push_back((int)std::distance(connI,i));
6415     }
6416   //
6417   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6418   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6419   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6420   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6421   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6422   //
6423   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6424   code.resize(3*nbOfCastsFinal);
6425   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6426   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6427   for(int i=0;i<nbOfCastsFinal;i++)
6428     {
6429       int castId=castsPresent->getIJ(i,0);
6430       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6431       idsInPflPerType2.push_back(tmp3);
6432       code[3*i]=(int)types[castId];
6433       code[3*i+1]=tmp3->getNumberOfTuples();
6434       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6435       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6436         {
6437           tmp4->copyStringInfoFrom(*profile);
6438           idsPerType2.push_back(tmp4);
6439           code[3*i+2]=(int)idsPerType2.size()-1;
6440         }
6441       else
6442         {
6443           code[3*i+2]=-1;
6444         }
6445     }
6446   std::size_t sz2=idsInPflPerType2.size();
6447   idsInPflPerType.resize(sz2);
6448   for(std::size_t i=0;i<sz2;i++)
6449     {
6450       DataArrayInt *locDa=idsInPflPerType2[i];
6451       locDa->incrRef();
6452       idsInPflPerType[i]=locDa;
6453     }
6454   std::size_t sz=idsPerType2.size();
6455   idsPerType.resize(sz);
6456   for(std::size_t i=0;i<sz;i++)
6457     {
6458       DataArrayInt *locDa=idsPerType2[i];
6459       locDa->incrRef();
6460       idsPerType[i]=locDa;
6461     }
6462 }
6463
6464 /*!
6465  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6466  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6467  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6468  * 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.
6469  */
6470 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6471 {
6472   checkFullyDefined();
6473   nM1LevMesh->checkFullyDefined();
6474   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6475     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6476   if(_coords!=nM1LevMesh->getCoords())
6477     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6478   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6479   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6480   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6481   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6482   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6483   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6484   tmp->setConnectivity(tmp0,tmp1);
6485   tmp->renumberCells(ret0->getConstPointer(),false);
6486   revDesc=tmp->getNodalConnectivity();
6487   revDescIndx=tmp->getNodalConnectivityIndex();
6488   DataArrayInt *ret=0;
6489   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6490     {
6491       int tmp2;
6492       ret->getMaxValue(tmp2);
6493       ret->decrRef();
6494       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6495       throw INTERP_KERNEL::Exception(oss.str().c_str());
6496     }
6497   nM1LevMeshIds=ret;
6498   //
6499   revDesc->incrRef();
6500   revDescIndx->incrRef();
6501   ret1->incrRef();
6502   ret0->incrRef();
6503   meshnM1Old2New=ret0;
6504   return ret1;
6505 }
6506
6507 /*!
6508  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6509  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6510  * in "Old to New" mode.
6511  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6512  *          this array using decrRef() as it is no more needed.
6513  *  \throw If the nodal connectivity of cells is not defined.
6514  */
6515 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6516 {
6517   checkConnectivityFullyDefined();
6518   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6519   renumberCells(ret->getConstPointer(),false);
6520   return ret.retn();
6521 }
6522
6523 /*!
6524  * This methods checks that cells are sorted by their types.
6525  * This method makes asumption (no check) that connectivity is correctly set before calling.
6526  */
6527 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6528 {
6529   checkFullyDefined();
6530   const int *conn=_nodal_connec->getConstPointer();
6531   const int *connI=_nodal_connec_index->getConstPointer();
6532   int nbOfCells=getNumberOfCells();
6533   std::set<INTERP_KERNEL::NormalizedCellType> types;
6534   for(const int *i=connI;i!=connI+nbOfCells;)
6535     {
6536       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6537       if(types.find(curType)!=types.end())
6538         return false;
6539       types.insert(curType);
6540       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6541     }
6542   return true;
6543 }
6544
6545 /*!
6546  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6547  * The geometric type order is specified by MED file.
6548  * 
6549  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6550  */
6551 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6552 {
6553   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6554 }
6555
6556 /*!
6557  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6558  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6559  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6560  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6561  */
6562 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6563 {
6564   checkFullyDefined();
6565   const int *conn=_nodal_connec->getConstPointer();
6566   const int *connI=_nodal_connec_index->getConstPointer();
6567   int nbOfCells=getNumberOfCells();
6568   if(nbOfCells==0)
6569     return true;
6570   int lastPos=-1;
6571   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6572   for(const int *i=connI;i!=connI+nbOfCells;)
6573     {
6574       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6575       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6576       if(isTypeExists!=orderEnd)
6577         {
6578           int pos=(int)std::distance(orderBg,isTypeExists);
6579           if(pos<=lastPos)
6580             return false;
6581           lastPos=pos;
6582           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6583         }
6584       else
6585         {
6586           if(sg.find(curType)==sg.end())
6587             {
6588               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6589               sg.insert(curType);
6590             }
6591           else
6592             return false;
6593         }
6594     }
6595   return true;
6596 }
6597
6598 /*!
6599  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6600  * 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
6601  * 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'.
6602  */
6603 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6604 {
6605   checkConnectivityFullyDefined();
6606   int nbOfCells=getNumberOfCells();
6607   const int *conn=_nodal_connec->getConstPointer();
6608   const int *connI=_nodal_connec_index->getConstPointer();
6609   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6610   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6611   tmpa->alloc(nbOfCells,1);
6612   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6613   tmpb->fillWithZero();
6614   int *tmp=tmpa->getPointer();
6615   int *tmp2=tmpb->getPointer();
6616   for(const int *i=connI;i!=connI+nbOfCells;i++)
6617     {
6618       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6619       if(where!=orderEnd)
6620         {
6621           int pos=(int)std::distance(orderBg,where);
6622           tmp2[pos]++;
6623           tmp[std::distance(connI,i)]=pos;
6624         }
6625       else
6626         {
6627           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6628           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6629           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6630           throw INTERP_KERNEL::Exception(oss.str().c_str());
6631         }
6632     }
6633   nbPerType=tmpb.retn();
6634   return tmpa.retn();
6635 }
6636
6637 /*!
6638  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6639  *
6640  * \return a new object containing the old to new correspondance.
6641  *
6642  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6643  */
6644 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6645 {
6646   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6647 }
6648
6649 /*!
6650  * 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.
6651  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6652  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6653  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6654  */
6655 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6656 {
6657   DataArrayInt *nbPerType=0;
6658   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6659   nbPerType->decrRef();
6660   return tmpa->buildPermArrPerLevel();
6661 }
6662
6663 /*!
6664  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6665  * The number of cells remains unchanged after the call of this method.
6666  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6667  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6668  *
6669  * \return the array giving the correspondance old to new.
6670  */
6671 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6672 {
6673   checkFullyDefined();
6674   computeTypes();
6675   const int *conn=_nodal_connec->getConstPointer();
6676   const int *connI=_nodal_connec_index->getConstPointer();
6677   int nbOfCells=getNumberOfCells();
6678   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6679   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6680     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6681       {
6682         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6683         types.push_back(curType);
6684         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6685       }
6686   DataArrayInt *ret=DataArrayInt::New();
6687   ret->alloc(nbOfCells,1);
6688   int *retPtr=ret->getPointer();
6689   std::fill(retPtr,retPtr+nbOfCells,-1);
6690   int newCellId=0;
6691   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6692     {
6693       for(const int *i=connI;i!=connI+nbOfCells;i++)
6694         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6695           retPtr[std::distance(connI,i)]=newCellId++;
6696     }
6697   renumberCells(retPtr,false);
6698   return ret;
6699 }
6700
6701 /*!
6702  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6703  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6704  * This method makes asumption that connectivity is correctly set before calling.
6705  */
6706 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6707 {
6708   checkFullyDefined();
6709   const int *conn=_nodal_connec->getConstPointer();
6710   const int *connI=_nodal_connec_index->getConstPointer();
6711   int nbOfCells=getNumberOfCells();
6712   std::vector<MEDCouplingUMesh *> ret;
6713   for(const int *i=connI;i!=connI+nbOfCells;)
6714     {
6715       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6716       int beginCellId=(int)std::distance(connI,i);
6717       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6718       int endCellId=(int)std::distance(connI,i);
6719       int sz=endCellId-beginCellId;
6720       int *cells=new int[sz];
6721       for(int j=0;j<sz;j++)
6722         cells[j]=beginCellId+j;
6723       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6724       delete [] cells;
6725       ret.push_back(m);
6726     }
6727   return ret;
6728 }
6729
6730 /*!
6731  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6732  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6733  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6734  *
6735  * \return a newly allocated instance, that the caller must manage.
6736  * \throw If \a this contains more than one geometric type.
6737  * \throw If the nodal connectivity of \a this is not fully defined.
6738  * \throw If the internal data is not coherent.
6739  */
6740 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6741 {
6742   checkConnectivityFullyDefined();
6743     if(_types.size()!=1)
6744     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6745   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6746   int typi=(int)typ;
6747   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6748   ret->setCoords(getCoords());
6749   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6750   if(retC)
6751     {
6752       int nbCells=getNumberOfCells();
6753       int nbNodesPerCell=retC->getNumberOfNodesPerCell();
6754       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6755       int *outPtr=connOut->getPointer();
6756       const int *conn=_nodal_connec->begin();
6757       const int *connI=_nodal_connec_index->begin();
6758       nbNodesPerCell++;
6759       for(int i=0;i<nbCells;i++,connI++)
6760         {
6761           if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6762             outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6763           else
6764             {
6765               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 << ") !";
6766               throw INTERP_KERNEL::Exception(oss.str().c_str());
6767             }
6768         }
6769       retC->setNodalConnectivity(connOut);
6770     }
6771   else
6772     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : not implemented yet for non static geometric type !");
6773   return ret.retn();
6774 }
6775
6776 /*!
6777  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6778  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6779  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6780  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6781  * are not used here to avoid the build of big permutation array.
6782  *
6783  * \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
6784  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6785  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6786  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6787  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6788  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6789  * \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
6790  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6791  */
6792 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6793                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6794                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6795 {
6796   std::vector<const MEDCouplingUMesh *> ms2;
6797   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6798     if(*it)
6799       {
6800         (*it)->checkConnectivityFullyDefined();
6801         ms2.push_back(*it);
6802       }
6803   if(ms2.empty())
6804     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6805   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6806   int meshDim=ms2[0]->getMeshDimension();
6807   std::vector<const MEDCouplingUMesh *> m1ssm;
6808   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6809   //
6810   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6811   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6812   int fake=0,rk=0;
6813   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6814   ret1->alloc(0,1); ret2->alloc(0,1);
6815   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6816     {
6817       if(meshDim!=(*it)->getMeshDimension())
6818         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6819       if(refCoo!=(*it)->getCoords())
6820         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6821       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6822       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6823       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6824       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6825         {
6826           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6827           m1ssmSingleAuto.push_back(singleCell);
6828           m1ssmSingle.push_back(singleCell);
6829           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6830         }
6831     }
6832   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6833   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6834   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6835   for(std::size_t i=0;i<m1ssm.size();i++)
6836     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6837   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6838   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6839   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6840   return ret0.retn();
6841 }
6842
6843 /*!
6844  * This method returns a newly created DataArrayInt instance.
6845  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6846  */
6847 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6848 {
6849   checkFullyDefined();
6850   const int *conn=_nodal_connec->getConstPointer();
6851   const int *connIndex=_nodal_connec_index->getConstPointer();
6852   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6853   for(const int *w=begin;w!=end;w++)
6854     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6855       ret->pushBackSilent(*w);
6856   return ret.retn();
6857 }
6858
6859 /*!
6860  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6861  * are in [0:getNumberOfCells())
6862  */
6863 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6864 {
6865   checkFullyDefined();
6866   const int *conn=_nodal_connec->getConstPointer();
6867   const int *connI=_nodal_connec_index->getConstPointer();
6868   int nbOfCells=getNumberOfCells();
6869   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6870   int *tmp=new int[nbOfCells];
6871   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6872     {
6873       int j=0;
6874       for(const int *i=connI;i!=connI+nbOfCells;i++)
6875         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6876           tmp[std::distance(connI,i)]=j++;
6877     }
6878   DataArrayInt *ret=DataArrayInt::New();
6879   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6880   ret->copyStringInfoFrom(*da);
6881   int *retPtr=ret->getPointer();
6882   const int *daPtr=da->getConstPointer();
6883   int nbOfElems=da->getNbOfElems();
6884   for(int k=0;k<nbOfElems;k++)
6885     retPtr[k]=tmp[daPtr[k]];
6886   delete [] tmp;
6887   return ret;
6888 }
6889
6890 /*!
6891  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6892  * This method \b works \b for mesh sorted by type.
6893  * cells whose ids is in 'idsPerGeoType' array.
6894  * This method conserves coords and name of mesh.
6895  */
6896 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6897 {
6898   std::vector<int> code=getDistributionOfTypes();
6899   std::size_t nOfTypesInThis=code.size()/3;
6900   int sz=0,szOfType=0;
6901   for(std::size_t i=0;i<nOfTypesInThis;i++)
6902     {
6903       if(code[3*i]!=type)
6904         sz+=code[3*i+1];
6905       else
6906         szOfType=code[3*i+1];
6907     }
6908   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6909     if(*work<0 || *work>=szOfType)
6910       {
6911         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6912         oss << ". It should be in [0," << szOfType << ") !";
6913         throw INTERP_KERNEL::Exception(oss.str().c_str());
6914       }
6915   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6916   int *idsPtr=idsTokeep->getPointer();
6917   int offset=0;
6918   for(std::size_t i=0;i<nOfTypesInThis;i++)
6919     {
6920       if(code[3*i]!=type)
6921         for(int j=0;j<code[3*i+1];j++)
6922           *idsPtr++=offset+j;
6923       else
6924         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6925       offset+=code[3*i+1];
6926     }
6927   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6928   ret->copyTinyInfoFrom(this);
6929   return ret.retn();
6930 }
6931
6932 /*!
6933  * This method returns a vector of size 'this->getNumberOfCells()'.
6934  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6935  */
6936 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6937 {
6938   int ncell=getNumberOfCells();
6939   std::vector<bool> ret(ncell);
6940   const int *cI=getNodalConnectivityIndex()->getConstPointer();
6941   const int *c=getNodalConnectivity()->getConstPointer();
6942   for(int i=0;i<ncell;i++)
6943     {
6944       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6945       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6946       ret[i]=cm.isQuadratic();
6947     }
6948   return ret;
6949 }
6950
6951 /*!
6952  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6953  */
6954 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6955 {
6956   if(other->getType()!=UNSTRUCTURED)
6957     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6958   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6959   return MergeUMeshes(this,otherC);
6960 }
6961
6962 /*!
6963  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6964  * computed by averaging coordinates of cell nodes, so this method is not a right
6965  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6966  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6967  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6968  *          components. The caller is to delete this array using decrRef() as it is
6969  *          no more needed.
6970  *  \throw If the coordinates array is not set.
6971  *  \throw If the nodal connectivity of cells is not defined.
6972  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6973  */
6974 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6975 {
6976   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6977   int spaceDim=getSpaceDimension();
6978   int nbOfCells=getNumberOfCells();
6979   ret->alloc(nbOfCells,spaceDim);
6980   ret->copyStringInfoFrom(*getCoords());
6981   double *ptToFill=ret->getPointer();
6982   const int *nodal=_nodal_connec->getConstPointer();
6983   const int *nodalI=_nodal_connec_index->getConstPointer();
6984   const double *coor=_coords->getConstPointer();
6985   for(int i=0;i<nbOfCells;i++)
6986     {
6987       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6988       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6989       ptToFill+=spaceDim;
6990     }
6991   return ret.retn();
6992 }
6993
6994 /*!
6995  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
6996  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
6997  * 
6998  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
6999  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7000  * 
7001  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7002  * \throw If \a this is not fully defined (coordinates and connectivity)
7003  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7004  */
7005 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7006 {
7007   checkFullyDefined();
7008   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7009   int spaceDim=getSpaceDimension();
7010   int nbOfCells=getNumberOfCells();
7011   int nbOfNodes=getNumberOfNodes();
7012   ret->alloc(nbOfCells,spaceDim);
7013   double *ptToFill=ret->getPointer();
7014   const int *nodal=_nodal_connec->getConstPointer();
7015   const int *nodalI=_nodal_connec_index->getConstPointer();
7016   const double *coor=_coords->getConstPointer();
7017   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7018     {
7019       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7020       std::fill(ptToFill,ptToFill+spaceDim,0.);
7021       if(type!=INTERP_KERNEL::NORM_POLYHED)
7022         {
7023           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7024             {
7025               if(*conn>=0 && *conn<nbOfNodes)
7026                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7027               else
7028                 {
7029                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7030                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7031                 }
7032             }
7033           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7034           if(nbOfNodesInCell>0)
7035             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7036           else
7037             {
7038               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7039               throw INTERP_KERNEL::Exception(oss.str().c_str());
7040             }
7041         }
7042       else
7043         {
7044           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7045           s.erase(-1);
7046           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7047             {
7048               if(*it>=0 && *it<nbOfNodes)
7049                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7050               else
7051                 {
7052                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7053                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7054                 }
7055             }
7056           if(!s.empty())
7057             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7058           else
7059             {
7060               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7061               throw INTERP_KERNEL::Exception(oss.str().c_str());
7062             }
7063         }
7064     }
7065   return ret.retn();
7066 }
7067
7068 /*!
7069  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7070  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7071  * are specified via an array of cell ids. 
7072  *  \warning Validity of the specified cell ids is not checked! 
7073  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7074  *  \param [in] begin - an array of cell ids of interest.
7075  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7076  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7077  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7078  *          caller is to delete this array using decrRef() as it is no more needed. 
7079  *  \throw If the coordinates array is not set.
7080  *  \throw If the nodal connectivity of cells is not defined.
7081  *
7082  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7083  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7084  */
7085 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7086 {
7087   DataArrayDouble *ret=DataArrayDouble::New();
7088   int spaceDim=getSpaceDimension();
7089   int nbOfTuple=(int)std::distance(begin,end);
7090   ret->alloc(nbOfTuple,spaceDim);
7091   double *ptToFill=ret->getPointer();
7092   double *tmp=new double[spaceDim];
7093   const int *nodal=_nodal_connec->getConstPointer();
7094   const int *nodalI=_nodal_connec_index->getConstPointer();
7095   const double *coor=_coords->getConstPointer();
7096   for(const int *w=begin;w!=end;w++)
7097     {
7098       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7099       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7100       ptToFill+=spaceDim;
7101     }
7102   delete [] tmp;
7103   return ret;
7104 }
7105
7106 /*!
7107  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7108  * 
7109  */
7110 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7111 {
7112   if(!da)
7113     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7114   da->checkAllocated();
7115   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7116   ret->setCoords(da);
7117   int nbOfTuples=da->getNumberOfTuples();
7118   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7119   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7120   c->alloc(2*nbOfTuples,1);
7121   cI->alloc(nbOfTuples+1,1);
7122   int *cp=c->getPointer();
7123   int *cip=cI->getPointer();
7124   *cip++=0;
7125   for(int i=0;i<nbOfTuples;i++)
7126     {
7127       *cp++=INTERP_KERNEL::NORM_POINT1;
7128       *cp++=i;
7129       *cip++=2*(i+1);
7130     }
7131   ret->setConnectivity(c,cI,true);
7132   return ret.retn();
7133 }
7134 /*!
7135  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7136  * Cells and nodes of
7137  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7138  *  \param [in] mesh1 - the first mesh.
7139  *  \param [in] mesh2 - the second mesh.
7140  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7141  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7142  *          is no more needed.
7143  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7144  *  \throw If the coordinates array is not set in none of the meshes.
7145  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7146  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7147  */
7148 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7149 {
7150   std::vector<const MEDCouplingUMesh *> tmp(2);
7151   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7152   return MergeUMeshes(tmp);
7153 }
7154
7155 /*!
7156  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7157  * Cells and nodes of
7158  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7159  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7160  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7161  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7162  *          is no more needed.
7163  *  \throw If \a a.size() == 0.
7164  *  \throw If \a a[ *i* ] == NULL.
7165  *  \throw If the coordinates array is not set in none of the meshes.
7166  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7167  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7168 */
7169 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7170 {
7171   std::size_t sz=a.size();
7172   if(sz==0)
7173     return MergeUMeshesLL(a);
7174   for(std::size_t ii=0;ii<sz;ii++)
7175     if(!a[ii])
7176       {
7177         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7178         throw INTERP_KERNEL::Exception(oss.str().c_str());
7179       }
7180   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7181   std::vector< const MEDCouplingUMesh * > aa(sz);
7182   int spaceDim=-3;
7183   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7184     {
7185       const MEDCouplingUMesh *cur=a[i];
7186       const DataArrayDouble *coo=cur->getCoords();
7187       if(coo)
7188         spaceDim=coo->getNumberOfComponents();
7189     }
7190   if(spaceDim==-3)
7191     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7192   for(std::size_t i=0;i<sz;i++)
7193     {
7194       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7195       aa[i]=bb[i];
7196     }
7197   return MergeUMeshesLL(aa);
7198 }
7199
7200 /// @cond INTERNAL
7201
7202 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7203 {
7204   if(a.empty())
7205     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7206   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7207   int meshDim=(*it)->getMeshDimension();
7208   int nbOfCells=(*it)->getNumberOfCells();
7209   int meshLgth=(*it++)->getMeshLength();
7210   for(;it!=a.end();it++)
7211     {
7212       if(meshDim!=(*it)->getMeshDimension())
7213         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7214       nbOfCells+=(*it)->getNumberOfCells();
7215       meshLgth+=(*it)->getMeshLength();
7216     }
7217   std::vector<const MEDCouplingPointSet *> aps(a.size());
7218   std::copy(a.begin(),a.end(),aps.begin());
7219   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7220   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7221   ret->setCoords(pts);
7222   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7223   c->alloc(meshLgth,1);
7224   int *cPtr=c->getPointer();
7225   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7226   cI->alloc(nbOfCells+1,1);
7227   int *cIPtr=cI->getPointer();
7228   *cIPtr++=0;
7229   int offset=0;
7230   int offset2=0;
7231   for(it=a.begin();it!=a.end();it++)
7232     {
7233       int curNbOfCell=(*it)->getNumberOfCells();
7234       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7235       const int *curC=(*it)->_nodal_connec->getConstPointer();
7236       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7237       for(int j=0;j<curNbOfCell;j++)
7238         {
7239           const int *src=curC+curCI[j];
7240           *cPtr++=*src++;
7241           for(;src!=curC+curCI[j+1];src++,cPtr++)
7242             {
7243               if(*src!=-1)
7244                 *cPtr=*src+offset2;
7245               else
7246                 *cPtr=-1;
7247             }
7248         }
7249       offset+=curCI[curNbOfCell];
7250       offset2+=(*it)->getNumberOfNodes();
7251     }
7252   //
7253   ret->setConnectivity(c,cI,true);
7254   return ret.retn();
7255 }
7256
7257 /// @endcond
7258
7259 /*!
7260  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7261  * dimension and sharing the node coordinates array.
7262  * All cells of the first mesh precede all cells of the second mesh
7263  * within the result mesh. 
7264  *  \param [in] mesh1 - the first mesh.
7265  *  \param [in] mesh2 - the second mesh.
7266  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7267  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7268  *          is no more needed.
7269  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7270  *  \throw If the meshes do not share the node coordinates array.
7271  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7272  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7273  */
7274 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7275 {
7276   std::vector<const MEDCouplingUMesh *> tmp(2);
7277   tmp[0]=mesh1; tmp[1]=mesh2;
7278   return MergeUMeshesOnSameCoords(tmp);
7279 }
7280
7281 /*!
7282  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7283  * dimension and sharing the node coordinates array.
7284  * All cells of the *i*-th mesh precede all cells of the
7285  * (*i*+1)-th mesh within the result mesh.
7286  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7287  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7288  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7289  *          is no more needed.
7290  *  \throw If \a a.size() == 0.
7291  *  \throw If \a a[ *i* ] == NULL.
7292  *  \throw If the meshes do not share the node coordinates array.
7293  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7294  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7295  */
7296 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7297 {
7298   if(meshes.empty())
7299     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7300   for(std::size_t ii=0;ii<meshes.size();ii++)
7301     if(!meshes[ii])
7302       {
7303         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7304         throw INTERP_KERNEL::Exception(oss.str().c_str());
7305       }
7306   const DataArrayDouble *coords=meshes.front()->getCoords();
7307   int meshDim=meshes.front()->getMeshDimension();
7308   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7309   int meshLgth=0;
7310   int meshIndexLgth=0;
7311   for(;iter!=meshes.end();iter++)
7312     {
7313       if(coords!=(*iter)->getCoords())
7314         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7315       if(meshDim!=(*iter)->getMeshDimension())
7316         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7317       meshLgth+=(*iter)->getMeshLength();
7318       meshIndexLgth+=(*iter)->getNumberOfCells();
7319     }
7320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7321   nodal->alloc(meshLgth,1);
7322   int *nodalPtr=nodal->getPointer();
7323   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7324   nodalIndex->alloc(meshIndexLgth+1,1);
7325   int *nodalIndexPtr=nodalIndex->getPointer();
7326   int offset=0;
7327   for(iter=meshes.begin();iter!=meshes.end();iter++)
7328     {
7329       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7330       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7331       int nbOfCells=(*iter)->getNumberOfCells();
7332       int meshLgth2=(*iter)->getMeshLength();
7333       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7334       if(iter!=meshes.begin())
7335         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7336       else
7337         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7338       offset+=meshLgth2;
7339     }
7340   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7341   ret->setName("merge");
7342   ret->setMeshDimension(meshDim);
7343   ret->setConnectivity(nodal,nodalIndex,true);
7344   ret->setCoords(coords);
7345   return ret;
7346 }
7347
7348 /*!
7349  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7350  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7351  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7352  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7353  * New" mode are returned for each input mesh.
7354  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7355  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7356  *          valid values [0,1,2], see zipConnectivityTraducer().
7357  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7358  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7359  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7360  *          no more needed.
7361  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7362  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7363  *          is no more needed.
7364  *  \throw If \a meshes.size() == 0.
7365  *  \throw If \a meshes[ *i* ] == NULL.
7366  *  \throw If the meshes do not share the node coordinates array.
7367  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7368  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7369  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7370  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7371  */
7372 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7373 {
7374   //All checks are delegated to MergeUMeshesOnSameCoords
7375   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7376   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7377   corr.resize(meshes.size());
7378   std::size_t nbOfMeshes=meshes.size();
7379   int offset=0;
7380   const int *o2nPtr=o2n->getConstPointer();
7381   for(std::size_t i=0;i<nbOfMeshes;i++)
7382     {
7383       DataArrayInt *tmp=DataArrayInt::New();
7384       int curNbOfCells=meshes[i]->getNumberOfCells();
7385       tmp->alloc(curNbOfCells,1);
7386       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7387       offset+=curNbOfCells;
7388       tmp->setName(meshes[i]->getName());
7389       corr[i]=tmp;
7390     }
7391   return ret.retn();
7392 }
7393
7394 /*!
7395  * Makes all given meshes share the nodal connectivity array. The common connectivity
7396  * array is created by concatenating the connectivity arrays of all given meshes. All
7397  * the given meshes must be of the same space dimension but dimension of cells **can
7398  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7399  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7400  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7401  *  \param [in,out] meshes - a vector of meshes to update.
7402  *  \throw If any of \a meshes is NULL.
7403  *  \throw If the coordinates array is not set in any of \a meshes.
7404  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7405  *  \throw If \a meshes are of different space dimension.
7406  */
7407 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7408 {
7409   std::size_t sz=meshes.size();
7410   if(sz==0 || sz==1)
7411     return;
7412   std::vector< const DataArrayDouble * > coords(meshes.size());
7413   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7414   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7415     {
7416       if((*it))
7417         {
7418           (*it)->checkConnectivityFullyDefined();
7419           const DataArrayDouble *coo=(*it)->getCoords();
7420           if(coo)
7421             *it2=coo;
7422           else
7423             {
7424               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7425               oss << " has no coordinate array defined !";
7426               throw INTERP_KERNEL::Exception(oss.str().c_str());
7427             }
7428         }
7429       else
7430         {
7431           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7432           oss << " is null !";
7433           throw INTERP_KERNEL::Exception(oss.str().c_str());
7434         }
7435     }
7436   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7437   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7438   int offset=(*it)->getNumberOfNodes();
7439   (*it++)->setCoords(res);
7440   for(;it!=meshes.end();it++)
7441     {
7442       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7443       (*it)->setCoords(res);
7444       (*it)->shiftNodeNumbersInConn(offset);
7445       offset+=oldNumberOfNodes;
7446     }
7447 }
7448
7449 /*!
7450  * Merges nodes coincident with a given precision within all given meshes that share
7451  * the nodal connectivity array. The given meshes **can be of different** mesh
7452  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7453  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7454  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7455  *  \param [in,out] meshes - a vector of meshes to update.
7456  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7457  *  \throw If any of \a meshes is NULL.
7458  *  \throw If the \a meshes do not share the same node coordinates array.
7459  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7460  */
7461 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7462 {
7463   if(meshes.empty())
7464     return ;
7465   std::set<const DataArrayDouble *> s;
7466   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7467     {
7468       if(*it)
7469         s.insert((*it)->getCoords());
7470       else
7471         {
7472           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 !";
7473           throw INTERP_KERNEL::Exception(oss.str().c_str());
7474         }
7475     }
7476   if(s.size()!=1)
7477     {
7478       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 !";
7479       throw INTERP_KERNEL::Exception(oss.str().c_str());
7480     }
7481   const DataArrayDouble *coo=*(s.begin());
7482   if(!coo)
7483     return;
7484   //
7485   DataArrayInt *comm,*commI;
7486   coo->findCommonTuples(eps,-1,comm,commI);
7487   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7488   int oldNbOfNodes=coo->getNumberOfTuples();
7489   int newNbOfNodes;
7490   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7491   if(oldNbOfNodes==newNbOfNodes)
7492     return ;
7493   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7494   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7495     {
7496       (*it)->renumberNodesInConn(o2n->getConstPointer());
7497       (*it)->setCoords(newCoords);
7498     } 
7499 }
7500
7501 /*!
7502  * 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.
7503  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7504  * \param isQuad specifies the policy of connectivity.
7505  * @ret in/out parameter in which the result will be append
7506  */
7507 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7508 {
7509   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7510   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7511   ret.push_back(cm.getExtrudedType());
7512   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7513   switch(flatType)
7514     {
7515     case INTERP_KERNEL::NORM_POINT1:
7516       {
7517         ret.push_back(connBg[1]);
7518         ret.push_back(connBg[1]+nbOfNodesPerLev);
7519         break;
7520       }
7521     case INTERP_KERNEL::NORM_SEG2:
7522       {
7523         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7524         ret.insert(ret.end(),conn,conn+4);
7525         break;
7526       }
7527     case INTERP_KERNEL::NORM_SEG3:
7528       {
7529         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7530         ret.insert(ret.end(),conn,conn+8);
7531         break;
7532       }
7533     case INTERP_KERNEL::NORM_QUAD4:
7534       {
7535         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7536         ret.insert(ret.end(),conn,conn+8);
7537         break;
7538       }
7539     case INTERP_KERNEL::NORM_TRI3:
7540       {
7541         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7542         ret.insert(ret.end(),conn,conn+6);
7543         break;
7544       }
7545     case INTERP_KERNEL::NORM_TRI6:
7546       {
7547         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,
7548                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7549         ret.insert(ret.end(),conn,conn+15);
7550         break;
7551       }
7552     case INTERP_KERNEL::NORM_QUAD8:
7553       {
7554         int conn[20]={
7555           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7556           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7557           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7558         };
7559         ret.insert(ret.end(),conn,conn+20);
7560         break;
7561       }
7562     case INTERP_KERNEL::NORM_POLYGON:
7563       {
7564         std::back_insert_iterator< std::vector<int> > ii(ret);
7565         std::copy(connBg+1,connEnd,ii);
7566         *ii++=-1;
7567         std::reverse_iterator<const int *> rConnBg(connEnd);
7568         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7569         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7570         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7571         for(std::size_t i=0;i<nbOfRadFaces;i++)
7572           {
7573             *ii++=-1;
7574             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7575             std::copy(conn,conn+4,ii);
7576           }
7577         break;
7578       }
7579     default:
7580       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7581     }
7582 }
7583
7584 /*!
7585  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7586  */
7587 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7588 {
7589   double v[3]={0.,0.,0.};
7590   std::size_t sz=std::distance(begin,end);
7591   if(isQuadratic)
7592     sz/=2;
7593   for(std::size_t i=0;i<sz;i++)
7594     {
7595       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];
7596       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7597       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7598     }
7599   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7600 }
7601
7602 /*!
7603  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7604  */
7605 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7606 {
7607   std::vector<std::pair<int,int> > edges;
7608   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7609   const int *bgFace=begin;
7610   for(std::size_t i=0;i<nbOfFaces;i++)
7611     {
7612       const int *endFace=std::find(bgFace+1,end,-1);
7613       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7614       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7615         {
7616           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7617           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7618             return false;
7619           edges.push_back(p1);
7620         }
7621       bgFace=endFace+1;
7622     }
7623   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7624 }
7625
7626 /*!
7627  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7628  */
7629 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7630 {
7631   double vec0[3],vec1[3];
7632   std::size_t sz=std::distance(begin,end);
7633   if(sz%2!=0)
7634     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7635   int nbOfNodes=(int)sz/2;
7636   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7637   const double *pt0=coords+3*begin[0];
7638   const double *pt1=coords+3*begin[nbOfNodes];
7639   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7640   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7641 }
7642
7643 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7644 {
7645   std::size_t sz=std::distance(begin,end);
7646   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7647   std::size_t nbOfNodes(sz/2);
7648   std::copy(begin,end,(int *)tmp);
7649   for(std::size_t j=1;j<nbOfNodes;j++)
7650     {
7651       begin[j]=tmp[nbOfNodes-j];
7652       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7653     }
7654 }
7655
7656 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7657 {
7658   std::size_t sz=std::distance(begin,end);
7659   if(sz!=4)
7660     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7661   double vec0[3],vec1[3];
7662   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7663   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]; 
7664   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;
7665 }
7666
7667 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7668 {
7669   std::size_t sz=std::distance(begin,end);
7670   if(sz!=5)
7671     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7672   double vec0[3];
7673   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7674   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7675   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7676 }
7677
7678 /*!
7679  * 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 ) 
7680  * 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
7681  * a 2D space.
7682  *
7683  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7684  * \param [in] coords the coordinates with nb of components exactly equal to 3
7685  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7686  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7687  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7688  */
7689 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7690 {
7691   int nbFaces=std::count(begin+1,end,-1)+1;
7692   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7693   double *vPtr=v->getPointer();
7694   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7695   double *pPtr=p->getPointer();
7696   const int *stFaceConn=begin+1;
7697   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7698     {
7699       const int *endFaceConn=std::find(stFaceConn,end,-1);
7700       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7701       stFaceConn=endFaceConn+1;
7702     }
7703   pPtr=p->getPointer(); vPtr=v->getPointer();
7704   DataArrayInt *comm1=0,*commI1=0;
7705   v->findCommonTuples(eps,-1,comm1,commI1);
7706   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7707   const int *comm1Ptr=comm1->getConstPointer();
7708   const int *commI1Ptr=commI1->getConstPointer();
7709   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7710   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7711   //
7712   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7713   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7714   mm->finishInsertingCells();
7715   //
7716   for(int i=0;i<nbOfGrps1;i++)
7717     {
7718       int vecId=comm1Ptr[commI1Ptr[i]];
7719       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7720       DataArrayInt *comm2=0,*commI2=0;
7721       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7722       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7723       const int *comm2Ptr=comm2->getConstPointer();
7724       const int *commI2Ptr=commI2->getConstPointer();
7725       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7726       for(int j=0;j<nbOfGrps2;j++)
7727         {
7728           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7729             {
7730               res->insertAtTheEnd(begin,end);
7731               res->pushBackSilent(-1);
7732             }
7733           else
7734             {
7735               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7736               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7737               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7738               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7739               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7740               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7741               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7742               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7743               const int *idsNodePtr=idsNode->getConstPointer();
7744               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];
7745               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7746               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7747               if(std::abs(norm)>eps)
7748                 {
7749                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7750                   mm3->rotate(center,vec,angle);
7751                 }
7752               mm3->changeSpaceDimension(2);
7753               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7754               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7755               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7756               int nbOfCells=mm4->getNumberOfCells();
7757               for(int k=0;k<nbOfCells;k++)
7758                 {
7759                   int l=0;
7760                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7761                     res->pushBackSilent(idsNodePtr[*work]);
7762                   res->pushBackSilent(-1);
7763                 }
7764             }
7765         }
7766     }
7767   res->popBackSilent();
7768 }
7769
7770 /*!
7771  * 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
7772  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7773  * 
7774  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7775  * \param [in] coords coordinates expected to have 3 components.
7776  * \param [in] begin start of the nodal connectivity of the face.
7777  * \param [in] end end of the nodal connectivity (excluded) of the face.
7778  * \param [out] v the normalized vector of size 3
7779  * \param [out] p the pos of plane
7780  */
7781 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7782 {
7783   std::size_t nbPoints=std::distance(begin,end);
7784   if(nbPoints<3)
7785     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7786   double vec[3]={0.,0.,0.};
7787   std::size_t j=0;
7788   bool refFound=false;
7789   for(;j<nbPoints-1 && !refFound;j++)
7790     {
7791       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7792       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7793       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7794       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7795       if(norm>eps)
7796         {
7797           refFound=true;
7798           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7799         }
7800     }
7801   for(std::size_t i=j;i<nbPoints-1;i++)
7802     {
7803       double curVec[3];
7804       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7805       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7806       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7807       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7808       if(norm<eps)
7809         continue;
7810       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7811       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];
7812       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7813       if(norm>eps)
7814         {
7815           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7816           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7817           return ;
7818         }
7819     }
7820   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7821 }
7822
7823 /*!
7824  * This method tries to obtain a well oriented polyhedron.
7825  * If the algorithm fails, an exception will be thrown.
7826  */
7827 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7828 {
7829   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7830   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7831   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7832   isPerm[0]=true;
7833   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7834   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7835   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7836   //
7837   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7838     {
7839       bgFace=begin;
7840       std::size_t smthChanged=0;
7841       for(std::size_t i=0;i<nbOfFaces;i++)
7842         {
7843           endFace=std::find(bgFace+1,end,-1);
7844           nbOfEdgesInFace=std::distance(bgFace,endFace);
7845           if(!isPerm[i])
7846             {
7847               bool b;
7848               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7849                 {
7850                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7851                   std::pair<int,int> p2(p1.second,p1.first);
7852                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7853                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7854                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7855                 }
7856               if(isPerm[i])
7857                 { 
7858                   if(!b)
7859                     std::reverse(bgFace+1,endFace);
7860                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7861                     {
7862                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7863                       std::pair<int,int> p2(p1.second,p1.first);
7864                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7865                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7866                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7867                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7868                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7869                       if(it!=edgesOK.end())
7870                         {
7871                           edgesOK.erase(it);
7872                           edgesFinished.push_back(p1);
7873                         }
7874                       else
7875                         edgesOK.push_back(p1);
7876                     }
7877                 }
7878             }
7879           bgFace=endFace+1;
7880         }
7881       if(smthChanged==0)
7882         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7883     }
7884   if(!edgesOK.empty())
7885     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7886   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7887     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7888       bgFace=begin;
7889       for(std::size_t i=0;i<nbOfFaces;i++)
7890         {
7891           endFace=std::find(bgFace+1,end,-1);
7892           std::reverse(bgFace+1,endFace);
7893           bgFace=endFace+1;
7894         }
7895     }
7896 }
7897
7898 /*!
7899  * This method makes the assumption spacedimension == meshdimension == 2.
7900  * This method works only for linear cells.
7901  * 
7902  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7903  */
7904 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7905 {
7906   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7907     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7908   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7909   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7910   int nbOfNodesExpected=m->getNumberOfNodes();
7911   if(m->getNumberOfCells()!=nbOfNodesExpected)
7912     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7913   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7914   const int *n2oPtr=n2o->getConstPointer();
7915   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7916   m->getReverseNodalConnectivity(revNodal,revNodalI);
7917   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7918   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7919   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7920   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7921   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
7922   if(nbOfNodesExpected<1)
7923     return ret.retn();
7924   int prevCell=0;
7925   int prevNode=nodalPtr[nodalIPtr[0]+1];
7926   *work++=n2oPtr[prevNode];
7927   for(int i=1;i<nbOfNodesExpected;i++)
7928     {
7929       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7930         {
7931           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7932           conn.erase(prevNode);
7933           if(conn.size()==1)
7934             {
7935               int curNode=*(conn.begin());
7936               *work++=n2oPtr[curNode];
7937               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7938               shar.erase(prevCell);
7939               if(shar.size()==1)
7940                 {
7941                   prevCell=*(shar.begin());
7942                   prevNode=curNode;
7943                 }
7944               else
7945                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
7946             }
7947           else
7948             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
7949         }
7950       else
7951         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
7952     }
7953   return ret.retn();
7954 }
7955
7956 /*!
7957  * This method makes the assumption spacedimension == meshdimension == 3.
7958  * This method works only for linear cells.
7959  * 
7960  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7961  */
7962 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
7963 {
7964   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7965     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7966   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7967   const int *conn=m->getNodalConnectivity()->getConstPointer();
7968   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
7969   int nbOfCells=m->getNumberOfCells();
7970   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7971   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
7972   if(nbOfCells<1)
7973     return ret.retn();
7974   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7975   for(int i=1;i<nbOfCells;i++)
7976     {
7977       *work++=-1;
7978       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7979     }
7980   return ret.retn();
7981 }
7982
7983 /*!
7984  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
7985  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
7986  */
7987 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
7988 {
7989   double *w=zipFrmt;
7990   if(spaceDim==3)
7991     for(int i=0;i<nbOfNodesInCell;i++)
7992       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
7993   else if(spaceDim==2)
7994     {
7995       for(int i=0;i<nbOfNodesInCell;i++)
7996         {
7997           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
7998           *w++=0.;
7999         }
8000     }
8001   else
8002     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8003 }
8004
8005 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8006 {
8007   int nbOfCells=getNumberOfCells();
8008   if(nbOfCells<=0)
8009     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8010   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};
8011   ofs << "  <" << getVTKDataSetType() << ">\n";
8012   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8013   ofs << "      <PointData>\n" << pointData << std::endl;
8014   ofs << "      </PointData>\n";
8015   ofs << "      <CellData>\n" << cellData << std::endl;
8016   ofs << "      </CellData>\n";
8017   ofs << "      <Points>\n";
8018   if(getSpaceDimension()==3)
8019     _coords->writeVTK(ofs,8,"Points");
8020   else
8021     {
8022       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8023       coo->writeVTK(ofs,8,"Points");
8024     }
8025   ofs << "      </Points>\n";
8026   ofs << "      <Cells>\n";
8027   const int *cPtr=_nodal_connec->getConstPointer();
8028   const int *cIPtr=_nodal_connec_index->getConstPointer();
8029   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8030   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8031   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8032   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8033   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8034   int szFaceOffsets=0,szConn=0;
8035   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8036     {
8037       *w2=cPtr[cIPtr[i]];
8038       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8039         {
8040           *w1=-1;
8041           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8042           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8043         }
8044       else
8045         {
8046           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8047           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8048           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8049           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8050           w4=std::copy(c.begin(),c.end(),w4);
8051         }
8052     }
8053   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8054   types->writeVTK(ofs,8,"UInt8","types");
8055   offsets->writeVTK(ofs,8,"Int32","offsets");
8056   if(szFaceOffsets!=0)
8057     {//presence of Polyhedra
8058       connectivity->reAlloc(szConn);
8059       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8060       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8061       w1=faces->getPointer();
8062       for(int i=0;i<nbOfCells;i++)
8063         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8064           {
8065             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8066             *w1++=nbFaces;
8067             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8068             for(int j=0;j<nbFaces;j++)
8069               {
8070                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8071                 *w1++=(int)std::distance(w6,w5);
8072                 w1=std::copy(w6,w5,w1);
8073                 w6=w5+1;
8074               }
8075           }
8076       faces->writeVTK(ofs,8,"Int32","faces");
8077     }
8078   connectivity->writeVTK(ofs,8,"Int32","connectivity");
8079   ofs << "      </Cells>\n";
8080   ofs << "    </Piece>\n";
8081   ofs << "  </" << getVTKDataSetType() << ">\n";
8082 }
8083
8084 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8085 {
8086   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8087   if(_mesh_dim==-2)
8088     { stream << " Not set !"; return ; }
8089   stream << " Mesh dimension : " << _mesh_dim << ".";
8090   if(_mesh_dim==-1)
8091     return ;
8092   if(!_coords)
8093     { stream << " No coordinates set !"; return ; }
8094   if(!_coords->isAllocated())
8095     { stream << " Coordinates set but not allocated !"; return ; }
8096   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8097   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8098   if(!_nodal_connec_index)
8099     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8100   if(!_nodal_connec_index->isAllocated())
8101     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8102   int lgth=_nodal_connec_index->getNumberOfTuples();
8103   int cpt=_nodal_connec_index->getNumberOfComponents();
8104   if(cpt!=1 || lgth<1)
8105     return ;
8106   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8107 }
8108
8109 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8110 {
8111   return std::string("UnstructuredGrid");
8112 }
8113
8114 /*!
8115  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8116  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8117  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8118  * meshes.
8119  *  \param [in] m1 - the first input mesh which is a partitioned object.
8120  *  \param [in] m2 - the second input mesh which is a partition tool.
8121  *  \param [in] eps - precision used to detect coincident mesh entities.
8122  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8123  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8124  *         this array using decrRef() as it is no more needed.
8125  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8126  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8127  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8128  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8129  *         it is no more needed.  
8130  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8131  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8132  *         is no more needed.  
8133  *  \throw If the coordinates array is not set in any of the meshes.
8134  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8135  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8136  */
8137 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8138 {
8139   m1->checkFullyDefined();
8140   m2->checkFullyDefined();
8141   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8142     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8143   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8144   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8145   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8146   std::vector<double> addCoo,addCoordsQuadratic;
8147   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8148   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8149   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8150                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8151   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8152   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8153   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8154   std::vector< std::vector<int> > intersectEdge2;
8155   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8156   subDiv2.clear(); dd5=0; dd6=0;
8157   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8158   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8159   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8160                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8161   //
8162   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8163   addCooDa->alloc((int)(addCoo.size())/2,2);
8164   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8165   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8166   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8167   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8168   std::vector<const DataArrayDouble *> coordss(4);
8169   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8170   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8171   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8172   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8173   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8174   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8175   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8176   ret->setConnectivity(conn,connI,true);
8177   ret->setCoords(coo);
8178   cellNb1=c1.retn(); cellNb2=c2.retn();
8179   return ret.retn();
8180 }
8181
8182 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8183                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8184                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8185                                                          const std::vector<double>& addCoords,
8186                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8187 {
8188   static const int SPACEDIM=2;
8189   std::vector<double> bbox1,bbox2;
8190   const double *coo1=m1->getCoords()->getConstPointer();
8191   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8192   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8193   int offset1=m1->getNumberOfNodes();
8194   const double *coo2=m2->getCoords()->getConstPointer();
8195   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8196   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8197   int offset2=offset1+m2->getNumberOfNodes();
8198   int offset3=offset2+((int)addCoords.size())/2;
8199   m1->getBoundingBoxForBBTree(bbox1);
8200   m2->getBoundingBoxForBBTree(bbox2);
8201   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8202   int ncell1=m1->getNumberOfCells();
8203   crI.push_back(0);
8204   for(int i=0;i<ncell1;i++)
8205     {
8206       std::vector<int> candidates2;
8207       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8208       std::map<INTERP_KERNEL::Node *,int> mapp;
8209       std::map<int,INTERP_KERNEL::Node *> mappRev;
8210       INTERP_KERNEL::QuadraticPolygon pol1;
8211       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8212       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8213       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8214       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8215                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8216       //
8217       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
8218       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8219       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8220       for(it1.first();!it1.finished();it1.next())
8221         edges1.insert(it1.current()->getPtr());
8222       //
8223       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8224       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8225       int ii=0;
8226       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8227         {
8228           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8229           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8230           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8231           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8232                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8233         }
8234       ii=0;
8235       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8236         {
8237           pol1.initLocationsWithOther(pol2s[ii]);
8238           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8239           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8240           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8241         }
8242       if(!edges1.empty())
8243         {
8244           try
8245             {
8246               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8247             }
8248           catch(INTERP_KERNEL::Exception& e)
8249             {
8250               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();
8251               throw INTERP_KERNEL::Exception(oss.str().c_str());
8252             }
8253         }
8254       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8255         (*it).second->decrRef();
8256     }
8257 }
8258
8259 /*!
8260  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8261  * 
8262  */
8263 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8264                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8265                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8266                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8267                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8268 {
8269   static const int SPACEDIM=2;
8270   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8271   desc2=DataArrayInt::New();
8272   descIndx2=DataArrayInt::New();
8273   revDesc2=DataArrayInt::New();
8274   revDescIndx2=DataArrayInt::New();
8275   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8276   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8277   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8278   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8279   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8280   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8281   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8282   std::vector<double> bbox1,bbox2;
8283   m1Desc->getBoundingBoxForBBTree(bbox1);
8284   m2Desc->getBoundingBoxForBBTree(bbox2);
8285   int ncell1=m1Desc->getNumberOfCells();
8286   int ncell2=m2Desc->getNumberOfCells();
8287   intersectEdge1.resize(ncell1);
8288   colinear2.resize(ncell2);
8289   subDiv2.resize(ncell2);
8290   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8291   std::vector<int> candidates1(1);
8292   int offset1=m1->getNumberOfNodes();
8293   int offset2=offset1+m2->getNumberOfNodes();
8294   for(int i=0;i<ncell1;i++)
8295     {
8296       std::vector<int> candidates2;
8297       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8298       if(!candidates2.empty())
8299         {
8300           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8301           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8302           candidates1[0]=i;
8303           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8304           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8305           delete pol2;
8306           delete pol1;
8307         }
8308       else
8309         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8310     }
8311   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8312   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8313 }
8314
8315 /*!
8316  * This method performs the 2nd step of Partition of 2D mesh.
8317  * This method has 4 inputs :
8318  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8319  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8320  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8321  * 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'
8322  * \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'
8323  * \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.
8324  * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8325  */
8326 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)
8327 {
8328   int offset1=m1->getNumberOfNodes();
8329   int ncell=m2->getNumberOfCells();
8330   const int *c=m2->getNodalConnectivity()->getConstPointer();
8331   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8332   const double *coo=m2->getCoords()->getConstPointer();
8333   const double *cooBis=m1->getCoords()->getConstPointer();
8334   int offset2=offset1+m2->getNumberOfNodes();
8335   intersectEdge.resize(ncell);
8336   for(int i=0;i<ncell;i++,cI++)
8337     {
8338       const std::vector<int>& divs=subDiv[i];
8339       int nnode=cI[1]-cI[0]-1;
8340       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8341       std::map<INTERP_KERNEL::Node *, int> mapp22;
8342       for(int j=0;j<nnode;j++)
8343         {
8344           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8345           int nnid=c[(*cI)+j+1];
8346           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8347           mapp22[nn]=nnid+offset1;
8348         }
8349       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8350       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8351         ((*it).second.first)->decrRef();
8352       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8353       std::map<INTERP_KERNEL::Node *,int> mapp3;
8354       for(std::size_t j=0;j<divs.size();j++)
8355         {
8356           int id=divs[j];
8357           INTERP_KERNEL::Node *tmp=0;
8358           if(id<offset1)
8359             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8360           else if(id<offset2)
8361             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8362           else
8363             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8364           addNodes[j]=tmp;
8365           mapp3[tmp]=id;
8366         }
8367       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8368       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8369         (*it)->decrRef();
8370       e->decrRef();
8371     }
8372 }
8373
8374 /*!
8375  * 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).
8376  * 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
8377  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8378  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8379  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8380  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8381  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8382  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8383  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8384  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8385  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8386  * \param [out] cut3DSuf input/output param.
8387  */
8388 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8389                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8390                                                    const int *desc, const int *descIndx, 
8391                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8392 {
8393   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8394   int nbOf3DSurfCell=(int)cut3DSurf.size();
8395   for(int i=0;i<nbOf3DSurfCell;i++)
8396     {
8397       std::vector<int> res;
8398       int offset=descIndx[i];
8399       int nbOfSeg=descIndx[i+1]-offset;
8400       for(int j=0;j<nbOfSeg;j++)
8401         {
8402           int edgeId=desc[offset+j];
8403           int status=cut3DCurve[edgeId];
8404           if(status!=-2)
8405             {
8406               if(status>-1)
8407                 res.push_back(status);
8408               else
8409                 {
8410                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8411                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8412                 }
8413             }
8414         }
8415       switch(res.size())
8416         {
8417         case 2:
8418           {
8419             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8420             break;
8421           }
8422         case 1:
8423         case 0:
8424           {
8425             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8426             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8427             if(res.size()==2)
8428               {
8429                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8430               }
8431             else
8432               {
8433                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8434               }
8435             break;
8436           }
8437         default:
8438           {// case when plane is on a multi colinear edge of a polyhedron
8439             if((int)res.size()==2*nbOfSeg)
8440               {
8441                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8442               }
8443             else
8444               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8445           }
8446         }
8447     }
8448 }
8449
8450 /*!
8451  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8452  * 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).
8453  * 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
8454  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8455  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8456  * \param desc is the descending connectivity 3D->3DSurf
8457  * \param descIndx is the descending connectivity index 3D->3DSurf
8458  */
8459 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8460                                                   const int *desc, const int *descIndx,
8461                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8462 {
8463   checkFullyDefined();
8464   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8465     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8466   const int *nodal3D=_nodal_connec->getConstPointer();
8467   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8468   int nbOfCells=getNumberOfCells();
8469   for(int i=0;i<nbOfCells;i++)
8470     {
8471       std::map<int, std::set<int> > m;
8472       int offset=descIndx[i];
8473       int nbOfFaces=descIndx[i+1]-offset;
8474       int start=-1;
8475       int end=-1;
8476       for(int j=0;j<nbOfFaces;j++)
8477         {
8478           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8479           if(p.first!=-1 && p.second!=-1)
8480             {
8481               if(p.first!=-2)
8482                 {
8483                   start=p.first; end=p.second;
8484                   m[p.first].insert(p.second);
8485                   m[p.second].insert(p.first);
8486                 }
8487               else
8488                 {
8489                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8490                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8491                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8492                   INTERP_KERNEL::NormalizedCellType cmsId;
8493                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8494                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8495                   for(unsigned k=0;k<nbOfNodesSon;k++)
8496                     {
8497                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8498                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8499                     }
8500                 }
8501             }
8502         }
8503       if(m.empty())
8504         continue;
8505       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8506       int prev=end;
8507       while(end!=start)
8508         {
8509           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8510           const std::set<int>& s=(*it).second;
8511           std::set<int> s2; s2.insert(prev);
8512           std::set<int> s3;
8513           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8514           if(s3.size()==1)
8515             {
8516               int val=*s3.begin();
8517               conn.push_back(start);
8518               prev=start;
8519               start=val;
8520             }
8521           else
8522             start=end;
8523         }
8524       conn.push_back(end);
8525       if(conn.size()>3)
8526         {
8527           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8528           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8529           cellIds->pushBackSilent(i);
8530         }
8531     }
8532 }
8533
8534 /*!
8535  * 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
8536  * 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
8537  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8538  * 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
8539  * 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.
8540  * 
8541  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8542  */
8543 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8544 {
8545   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8546   if(sz>=4)
8547     {
8548       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8549       if(cm.getDimension()==2)
8550         {
8551           const int *node=nodalConnBg+1;
8552           int startNode=*node++;
8553           double refX=coords[2*startNode];
8554           for(;node!=nodalConnEnd;node++)
8555             {
8556               if(coords[2*(*node)]<refX)
8557                 {
8558                   startNode=*node;
8559                   refX=coords[2*startNode];
8560                 }
8561             }
8562           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8563           refX=1e300;
8564           double tmp1;
8565           double tmp2[2];
8566           double angle0=-M_PI/2;
8567           //
8568           int nextNode=-1;
8569           int prevNode=-1;
8570           double resRef;
8571           double angleNext=0.;
8572           while(nextNode!=startNode)
8573             {
8574               nextNode=-1;
8575               resRef=1e300;
8576               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8577                 {
8578                   if(*node!=tmpOut.back() && *node!=prevNode)
8579                     {
8580                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8581                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8582                       double res;
8583                       if(angleM<=angle0)
8584                         res=angle0-angleM;
8585                       else
8586                         res=angle0-angleM+2.*M_PI;
8587                       if(res<resRef)
8588                         {
8589                           nextNode=*node;
8590                           resRef=res;
8591                           angleNext=angleM;
8592                         }
8593                     }
8594                 }
8595               if(nextNode!=startNode)
8596                 {
8597                   angle0=angleNext-M_PI;
8598                   if(angle0<-M_PI)
8599                     angle0+=2*M_PI;
8600                   prevNode=tmpOut.back();
8601                   tmpOut.push_back(nextNode);
8602                 }
8603             }
8604           std::vector<int> tmp3(2*(sz-1));
8605           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8606           std::copy(nodalConnBg+1,nodalConnEnd,it);
8607           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8608             {
8609               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8610               return false;
8611             }
8612           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8613             {
8614               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8615               return false;
8616             }
8617           else
8618             {
8619               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8620               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8621               return true;
8622             }
8623         }
8624       else
8625         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8626     }
8627   else
8628     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8629 }
8630
8631 /*!
8632  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8633  * 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.
8634  * 
8635  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8636  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8637  * \param [in,out] arr array in which the remove operation will be done.
8638  * \param [in,out] arrIndx array in the remove operation will modify
8639  * \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])
8640  * \return true if \b arr and \b arrIndx have been modified, false if not.
8641  */
8642 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8643 {
8644   if(!arrIndx || !arr)
8645     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8646   if(offsetForRemoval<0)
8647     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8648   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8649   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8650   int *arrIPtr=arrIndx->getPointer();
8651   *arrIPtr++=0;
8652   int previousArrI=0;
8653   const int *arrPtr=arr->getConstPointer();
8654   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8655   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8656     {
8657       if(*arrIPtr-previousArrI>offsetForRemoval)
8658         {
8659           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8660             {
8661               if(s.find(*work)==s.end())
8662                 arrOut.push_back(*work);
8663             }
8664         }
8665       previousArrI=*arrIPtr;
8666       *arrIPtr=(int)arrOut.size();
8667     }
8668   if(arr->getNumberOfTuples()==(int)arrOut.size())
8669     return false;
8670   arr->alloc((int)arrOut.size(),1);
8671   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8672   return true;
8673 }
8674
8675 /*!
8676  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8677  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8678  * The selection of extraction is done standardly in new2old format.
8679  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8680  *
8681  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8682  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8683  * \param [in] arrIn arr origin array from which the extraction will be done.
8684  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8685  * \param [out] arrOut the resulting array
8686  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8687  */
8688 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8689                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8690 {
8691   if(!arrIn || !arrIndxIn)
8692     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8693   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8694   const int *arrInPtr=arrIn->getConstPointer();
8695   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8696   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8697   int maxSizeOfArr=arrIn->getNumberOfTuples();
8698   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8699   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8700   arrIo->alloc((int)(sz+1),1);
8701   const int *idsIt=idsOfSelectBg;
8702   int *work=arrIo->getPointer();
8703   *work++=0;
8704   int lgth=0;
8705   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8706     {
8707       if(*idsIt>=0 && *idsIt<nbOfGrps)
8708         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8709       else
8710         {
8711           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8712           throw INTERP_KERNEL::Exception(oss.str().c_str());
8713         }
8714       if(lgth>=work[-1])
8715         *work=lgth;
8716       else
8717         {
8718           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8719           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8720           throw INTERP_KERNEL::Exception(oss.str().c_str());
8721         }
8722     }
8723   arro->alloc(lgth,1);
8724   work=arro->getPointer();
8725   idsIt=idsOfSelectBg;
8726   for(std::size_t i=0;i<sz;i++,idsIt++)
8727     {
8728       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8729         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8730       else
8731         {
8732           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8733           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8734           throw INTERP_KERNEL::Exception(oss.str().c_str());
8735         }
8736     }
8737   arrOut=arro.retn();
8738   arrIndexOut=arrIo.retn();
8739 }
8740
8741 /*!
8742  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8743  * 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
8744  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8745  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8746  *
8747  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8748  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8749  * \param [in] arrIn arr origin array from which the extraction will be done.
8750  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8751  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8752  * \param [in] srcArrIndex index array of \b srcArr
8753  * \param [out] arrOut the resulting array
8754  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8755  * 
8756  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8757  */
8758 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8759                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8760                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8761 {
8762   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8763     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8764   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8765   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8766   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8767   std::vector<bool> v(nbOfTuples,true);
8768   int offset=0;
8769   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8770   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8771   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8772     {
8773       if(*it>=0 && *it<nbOfTuples)
8774         {
8775           v[*it]=false;
8776           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8777         }
8778       else
8779         {
8780           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8781           throw INTERP_KERNEL::Exception(oss.str().c_str());
8782         }
8783     }
8784   srcArrIndexPtr=srcArrIndex->getConstPointer();
8785   arrIo->alloc(nbOfTuples+1,1);
8786   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8787   const int *arrInPtr=arrIn->getConstPointer();
8788   const int *srcArrPtr=srcArr->getConstPointer();
8789   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8790   int *arroPtr=arro->getPointer();
8791   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8792     {
8793       if(v[ii])
8794         {
8795           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8796           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8797         }
8798       else
8799         {
8800           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8801           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8802           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8803         }
8804     }
8805   arrOut=arro.retn();
8806   arrIndexOut=arrIo.retn();
8807 }
8808
8809 /*!
8810  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8811  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8812  *
8813  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8814  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8815  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8816  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8817  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8818  * \param [in] srcArrIndex index array of \b srcArr
8819  * 
8820  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8821  */
8822 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8823                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8824 {
8825   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8826     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8827   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8828   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8829   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8830   int *arrInOutPtr=arrInOut->getPointer();
8831   const int *srcArrPtr=srcArr->getConstPointer();
8832   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8833     {
8834       if(*it>=0 && *it<nbOfTuples)
8835         {
8836           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8837             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8838           else
8839             {
8840               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] !";
8841               throw INTERP_KERNEL::Exception(oss.str().c_str());
8842             }
8843         }
8844       else
8845         {
8846           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8847           throw INTERP_KERNEL::Exception(oss.str().c_str());
8848         }
8849     }
8850 }
8851
8852 /*!
8853  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8854  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8855  * 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]].
8856  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8857  * A negative value in \b arrIn means that it is ignored.
8858  * 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.
8859  * 
8860  * \param [in] arrIn arr origin array from which the extraction will be done.
8861  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8862  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8863  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8864  */
8865 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
8866 {
8867   int seed=0,nbOfDepthPeelingPerformed=0;
8868   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
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  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8879  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8880  * \param [in] arrIn arr origin array from which the extraction will be done.
8881  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8882  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8883  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8884  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8885  * \sa MEDCouplingUMesh::partitionBySpreadZone
8886  */
8887 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8888 {
8889   nbOfDepthPeelingPerformed=0;
8890   if(!arrIndxIn)
8891     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8892   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8893   if(nbOfTuples<=0)
8894     {
8895       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8896       return ret;
8897     }
8898   //
8899   std::vector<bool> fetched(nbOfTuples,false);
8900   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8901 }
8902
8903 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)
8904 {
8905   nbOfDepthPeelingPerformed=0;
8906   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
8907     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
8908   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8909   std::vector<bool> fetched2(nbOfTuples,false);
8910   int i=0;
8911   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
8912     {
8913       if(*seedElt>=0 && *seedElt<nbOfTuples)
8914         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
8915       else
8916         { 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()); }
8917     }
8918   const int *arrInPtr=arrIn->getConstPointer();
8919   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8920   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
8921   std::vector<int> idsToFetch1(seedBg,seedEnd);
8922   std::vector<int> idsToFetch2;
8923   std::vector<int> *idsToFetch=&idsToFetch1;
8924   std::vector<int> *idsToFetchOther=&idsToFetch2;
8925   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
8926     {
8927       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
8928         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
8929           if(!fetched[*it2])
8930             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
8931       std::swap(idsToFetch,idsToFetchOther);
8932       idsToFetchOther->clear();
8933       nbOfDepthPeelingPerformed++;
8934     }
8935   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
8936   i=0;
8937   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
8938   int *retPtr=ret->getPointer();
8939   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
8940     if(*it)
8941       *retPtr++=i;
8942   return ret.retn();
8943 }
8944
8945 /*!
8946  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8947  * 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
8948  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8949  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8950  *
8951  * \param [in] start begin of set of ids of the input extraction (included)
8952  * \param [in] end end of set of ids of the input extraction (excluded)
8953  * \param [in] step step of the set of ids in range mode.
8954  * \param [in] arrIn arr origin array from which the extraction will be done.
8955  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8956  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8957  * \param [in] srcArrIndex index array of \b srcArr
8958  * \param [out] arrOut the resulting array
8959  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8960  * 
8961  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8962  */
8963 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8964                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8965                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8966 {
8967   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8968     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
8969   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8970   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8971   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8972   int offset=0;
8973   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8974   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8975   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
8976   int it=start;
8977   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8978     {
8979       if(it>=0 && it<nbOfTuples)
8980         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
8981       else
8982         {
8983           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8984           throw INTERP_KERNEL::Exception(oss.str().c_str());
8985         }
8986     }
8987   srcArrIndexPtr=srcArrIndex->getConstPointer();
8988   arrIo->alloc(nbOfTuples+1,1);
8989   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8990   const int *arrInPtr=arrIn->getConstPointer();
8991   const int *srcArrPtr=srcArr->getConstPointer();
8992   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8993   int *arroPtr=arro->getPointer();
8994   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8995     {
8996       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
8997       if(pos<0)
8998         {
8999           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9000           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9001         }
9002       else
9003         {
9004           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9005           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9006         }
9007     }
9008   arrOut=arro.retn();
9009   arrIndexOut=arrIo.retn();
9010 }
9011
9012 /*!
9013  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9014  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9015  *
9016  * \param [in] start begin of set of ids of the input extraction (included)
9017  * \param [in] end end of set of ids of the input extraction (excluded)
9018  * \param [in] step step of the set of ids in range mode.
9019  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9020  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9021  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9022  * \param [in] srcArrIndex index array of \b srcArr
9023  * 
9024  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9025  */
9026 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9027                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9028 {
9029   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9030     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9031   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9032   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9033   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9034   int *arrInOutPtr=arrInOut->getPointer();
9035   const int *srcArrPtr=srcArr->getConstPointer();
9036   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9037   int it=start;
9038   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9039     {
9040       if(it>=0 && it<nbOfTuples)
9041         {
9042           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9043             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9044           else
9045             {
9046               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9047               throw INTERP_KERNEL::Exception(oss.str().c_str());
9048             }
9049         }
9050       else
9051         {
9052           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9053           throw INTERP_KERNEL::Exception(oss.str().c_str());
9054         }
9055     }
9056 }
9057
9058 /*!
9059  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9060  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9061  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9062  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9063  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9064  * 
9065  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9066  */
9067 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9068 {
9069   checkFullyDefined();
9070   int mdim=getMeshDimension();
9071   int spaceDim=getSpaceDimension();
9072   if(mdim!=spaceDim)
9073     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9074   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9075   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9076   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9077   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9078   ret->setCoords(getCoords());
9079   ret->allocateCells((int)partition.size());
9080   //
9081   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9082     {
9083       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9084       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9085       switch(mdim)
9086         {
9087         case 2:
9088           cell=tmp->buildUnionOf2DMesh();
9089           break;
9090         case 3:
9091           cell=tmp->buildUnionOf3DMesh();
9092           break;
9093         default:
9094           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9095         }
9096       
9097       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9098     }
9099   //
9100   ret->finishInsertingCells();
9101   return ret.retn();
9102 }
9103
9104 /*!
9105  * This method partitions \b this into contiguous zone.
9106  * This method only needs a well defined connectivity. Coordinates are not considered here.
9107  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9108  */
9109 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9110 {
9111   //#if 0
9112   int nbOfCellsCur=getNumberOfCells();
9113   std::vector<DataArrayInt *> ret;
9114   if(nbOfCellsCur<=0)
9115     return ret;
9116   DataArrayInt *neigh=0,*neighI=0;
9117   computeNeighborsOfCells(neigh,neighI);
9118   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9119   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9120   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9121   int seed=0;
9122   while(seed<nbOfCellsCur)
9123     {
9124       int nbOfPeelPerformed=0;
9125       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9126       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9127     }
9128   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9129     ret.push_back((*it).retn());
9130   return ret;
9131   //#endif
9132 #if 0
9133   int nbOfCellsCur=getNumberOfCells();
9134   DataArrayInt *neigh=0,*neighI=0;
9135   computeNeighborsOfCells(neigh,neighI);
9136   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9137   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9138   std::vector<DataArrayInt *> ret;
9139   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9140   while(nbOfCellsCur>0)
9141     {
9142       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9143       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9144       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9145       ret2.push_back(tmp2);  ret.push_back(tmp2);
9146       nbOfCellsCur=tmp3->getNumberOfTuples();
9147       if(nbOfCellsCur>0)
9148         {
9149           ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9150           MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9151           neighAuto=neigh;
9152           neighIAuto=neighI;
9153           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9154           neighAuto->transformWithIndArr(renum->begin(),renum->end());
9155         }
9156     }
9157   for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9158     (*it)->incrRef();
9159   return ret;
9160 #endif
9161 }
9162
9163 /*!
9164  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9165  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9166  *
9167  * \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.
9168  * \return a newly allocated DataArrayInt to be managed by the caller.
9169  * \throw In case of \a code has not the right format (typically of size 3*n)
9170  */
9171 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9172 {
9173   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9174   std::size_t nb=code.size()/3;
9175   if(code.size()%3!=0)
9176     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9177   ret->alloc((int)nb,2);
9178   int *retPtr=ret->getPointer();
9179   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9180     {
9181       retPtr[0]=code[3*i+2];
9182       retPtr[1]=code[3*i+2]+code[3*i+1];
9183     }
9184   return ret.retn();
9185 }
9186
9187 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9188                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9189 {
9190   if(mesh)
9191     {
9192       mesh->incrRef();
9193       _nb_cell=mesh->getNumberOfCells();
9194     }
9195 }
9196
9197 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9198 {
9199   if(_mesh)
9200     _mesh->decrRef();
9201   if(_own_cell)
9202     delete _cell;
9203 }
9204
9205 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9206                                                                                                                                _own_cell(false),_cell_id(bg-1),
9207                                                                                                                                _nb_cell(end)
9208 {
9209   if(mesh)
9210     mesh->incrRef();
9211 }
9212
9213 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9214 {
9215   _cell_id++;
9216   if(_cell_id<_nb_cell)
9217     {
9218       _cell->next();
9219       return _cell;
9220     }
9221   else
9222     return 0;
9223 }
9224
9225 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9226 {
9227   if(_mesh)
9228     _mesh->incrRef();
9229 }
9230
9231 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9232 {
9233   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9234 }
9235
9236 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9237 {
9238   if(_mesh)
9239     _mesh->decrRef();
9240 }
9241
9242 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9243                                                                                                                                                                   _itc(itc),
9244                                                                                                                                                                   _bg(bg),_end(end)
9245 {
9246   if(_mesh)
9247     _mesh->incrRef();
9248 }
9249
9250 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9251 {
9252   if(_mesh)
9253     _mesh->decrRef();
9254 }
9255
9256 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9257 {
9258   return _type;
9259 }
9260
9261 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9262 {
9263   return _end-_bg;
9264 }
9265
9266 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9267 {
9268   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9269 }
9270
9271 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9272 {
9273   if(mesh)
9274     {
9275       mesh->incrRef();
9276       _nb_cell=mesh->getNumberOfCells();
9277     }
9278 }
9279
9280 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9281 {
9282   if(_mesh)
9283     _mesh->decrRef();
9284   delete _cell;
9285 }
9286
9287 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9288 {
9289   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9290   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9291   if(_cell_id<_nb_cell)
9292     {
9293       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9294       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9295       int startId=_cell_id;
9296       _cell_id+=nbOfElems;
9297       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9298     }
9299   else
9300     return 0;
9301 }
9302
9303 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9304 {
9305   if(mesh)
9306     {
9307       _conn=mesh->getNodalConnectivity()->getPointer();
9308       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9309     }
9310 }
9311
9312 void MEDCouplingUMeshCell::next()
9313 {
9314   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9315     {
9316       _conn+=_conn_lgth;
9317       _conn_indx++;
9318     }
9319   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9320 }
9321
9322 std::string MEDCouplingUMeshCell::repr() const
9323 {
9324   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9325     {
9326       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9327       oss << " : ";
9328       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9329       return oss.str();
9330     }
9331   else
9332     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9333 }
9334
9335 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9336 {
9337   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9338     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9339   else
9340     return INTERP_KERNEL::NORM_ERROR;
9341 }
9342
9343 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9344 {
9345   lgth=_conn_lgth;
9346   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9347     return _conn;
9348   else
9349     return 0;
9350 }