Salome HOME
improve perf of convertToPolyTypes
[modules/med.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.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 std::string& 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 /*!
93  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94  * The coordinates are shared between \a this and the returned instance.
95  * 
96  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97  * \sa MEDCouplingUMesh::deepCpy
98  */
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
100 {
101   checkConnectivityFullyDefined();
102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104   ret->setConnectivity(c,ci);
105   return ret.retn();
106 }
107
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
109 {
110   if(!other)
111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
113   if(!otherC)
114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
117 }
118
119 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
120 {
121   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
122   return ret;
123 }
124
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildren() const
126 {
127   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildren());
128   if(_nodal_connec)
129     ret.push_back(_nodal_connec);
130   if(_nodal_connec_index)
131     ret.push_back(_nodal_connec_index);
132   return ret;
133 }
134
135 void MEDCouplingUMesh::updateTime() const
136 {
137   MEDCouplingPointSet::updateTime();
138   if(_nodal_connec)
139     {
140       updateTimeWith(*_nodal_connec);
141     }
142   if(_nodal_connec_index)
143     {
144       updateTimeWith(*_nodal_connec_index);
145     }
146 }
147
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
149 {
150 }
151
152 /*!
153  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154  * then \a this mesh is most probably is writable, exchangeable and available for most
155  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156  * this method to check that all is in order with \a this mesh.
157  *  \throw If the mesh dimension is not set.
158  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
159  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160  *  \throw If the connectivity data array has more than one component.
161  *  \throw If the connectivity data array has a named component.
162  *  \throw If the connectivity index data array has more than one component.
163  *  \throw If the connectivity index data array has a named component.
164  */
165 void MEDCouplingUMesh::checkCoherency() const
166 {
167   if(_mesh_dim<-1)
168    throw INTERP_KERNEL::Exception("No mesh dimension specified !");
169   if(_mesh_dim!=-1)
170     MEDCouplingPointSet::checkCoherency();
171   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
172     {
173       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
174         {
175           std::ostringstream message;
176           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177           throw INTERP_KERNEL::Exception(message.str().c_str());
178         }
179     }
180   if(_nodal_connec)
181     {
182       if(_nodal_connec->getNumberOfComponents()!=1)
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184       if(_nodal_connec->getInfoOnComponent(0)!="")
185         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
186     }
187   else
188     if(_mesh_dim!=-1)
189       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190   if(_nodal_connec_index)
191     {
192       if(_nodal_connec_index->getNumberOfComponents()!=1)
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194       if(_nodal_connec_index->getInfoOnComponent(0)!="")
195         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
196     }
197   else
198     if(_mesh_dim!=-1)
199       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
200 }
201
202 /*!
203  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204  * then \a this mesh is most probably is writable, exchangeable and available for all
205  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206  * method thoroughly checks the nodal connectivity.
207  *  \param [in] eps - a not used parameter.
208  *  \throw If the mesh dimension is not set.
209  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
210  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211  *  \throw If the connectivity data array has more than one component.
212  *  \throw If the connectivity data array has a named component.
213  *  \throw If the connectivity index data array has more than one component.
214  *  \throw If the connectivity index data array has a named component.
215  *  \throw If number of nodes defining an element does not correspond to the type of element.
216  *  \throw If the nodal connectivity includes an invalid node id.
217  */
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
219 {
220   checkCoherency();
221   if(_mesh_dim==-1)
222     return ;
223   int meshDim=getMeshDimension();
224   int nbOfNodes=getNumberOfNodes();
225   int nbOfCells=getNumberOfCells();
226   const int *ptr=_nodal_connec->getConstPointer();
227   const int *ptrI=_nodal_connec_index->getConstPointer();
228   for(int i=0;i<nbOfCells;i++)
229     {
230       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231       if((int)cm.getDimension()!=meshDim)
232         {
233           std::ostringstream oss;
234           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235           throw INTERP_KERNEL::Exception(oss.str().c_str());
236         }
237       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
238       if(!cm.isDynamic())
239         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
240           {
241             std::ostringstream oss;
242             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
243             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244             throw INTERP_KERNEL::Exception(oss.str().c_str());
245           }
246       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
247         {
248           int nodeId=*w;
249           if(nodeId>=0)
250             {
251               if(nodeId>=nbOfNodes)
252                 {
253                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
254                   throw INTERP_KERNEL::Exception(oss.str().c_str());
255                 }
256             }
257           else if(nodeId<-1)
258             {
259               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
260               throw INTERP_KERNEL::Exception(oss.str().c_str());
261             }
262           else
263             {
264               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
265                 {
266                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
267                   throw INTERP_KERNEL::Exception(oss.str().c_str());
268                 }
269             }
270         }
271     }
272 }
273
274
275 /*!
276  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
277  * then \a this mesh is most probably is writable, exchangeable and available for all
278  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
279  *  \param [in] eps - a not used parameter.
280  *  \throw If the mesh dimension is not set.
281  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
282  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
283  *  \throw If the connectivity data array has more than one component.
284  *  \throw If the connectivity data array has a named component.
285  *  \throw If the connectivity index data array has more than one component.
286  *  \throw If the connectivity index data array has a named component.
287  *  \throw If number of nodes defining an element does not correspond to the type of element.
288  *  \throw If the nodal connectivity includes an invalid node id.
289  */
290 void MEDCouplingUMesh::checkCoherency2(double eps) const
291 {
292   checkCoherency1(eps);
293 }
294
295 /*!
296  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
297  * elements contained in the mesh. For more info on the mesh dimension see
298  * \ref MEDCouplingUMeshPage.
299  *  \param [in] meshDim - a new mesh dimension.
300  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
301  */
302 void MEDCouplingUMesh::setMeshDimension(int meshDim)
303 {
304   if(meshDim<-1 || meshDim>3)
305     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
306   _mesh_dim=meshDim;
307   declareAsNew();
308 }
309
310 /*!
311  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
312  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
313  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
314  *
315  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
316  *
317  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
318  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
319  */
320 void MEDCouplingUMesh::allocateCells(int nbOfCells)
321 {
322   if(nbOfCells<0)
323     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
324   if(_nodal_connec_index)
325     {
326       _nodal_connec_index->decrRef();
327     }
328   if(_nodal_connec)
329     {
330       _nodal_connec->decrRef();
331     }
332   _nodal_connec_index=DataArrayInt::New();
333   _nodal_connec_index->reserve(nbOfCells+1);
334   _nodal_connec_index->pushBackSilent(0);
335   _nodal_connec=DataArrayInt::New();
336   _nodal_connec->reserve(2*nbOfCells);
337   _types.clear();
338   declareAsNew();
339 }
340
341 /*!
342  * Appends a cell to the connectivity array. For deeper understanding what is
343  * happening see \ref MEDCouplingUMeshNodalConnectivity.
344  *  \param [in] type - type of cell to add.
345  *  \param [in] size - number of nodes constituting this cell.
346  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
347  * 
348  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
349  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
350  */
351 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
352 {
353   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
354   if(_nodal_connec_index==0)
355     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
356   if((int)cm.getDimension()==_mesh_dim)
357     {
358       if(!cm.isDynamic())
359         if(size!=(int)cm.getNumberOfNodes())
360           {
361             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
362             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
363             throw INTERP_KERNEL::Exception(oss.str().c_str());
364           }
365       int idx=_nodal_connec_index->back();
366       int val=idx+size+1;
367       _nodal_connec_index->pushBackSilent(val);
368       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
369       _types.insert(type);
370     }
371   else
372     {
373       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
374       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
375       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
376       throw INTERP_KERNEL::Exception(oss.str().c_str());
377     }
378 }
379
380 /*!
381  * Compacts data arrays to release unused memory. This method is to be called after
382  * finishing cell insertion using \a this->insertNextCell().
383  * 
384  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
385  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
386  */
387 void MEDCouplingUMesh::finishInsertingCells()
388 {
389   _nodal_connec->pack();
390   _nodal_connec_index->pack();
391   _nodal_connec->declareAsNew();
392   _nodal_connec_index->declareAsNew();
393   updateTime();
394 }
395
396 /*!
397  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
398  * Useful for python users.
399  */
400 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
401 {
402   return new MEDCouplingUMeshCellIterator(this);
403 }
404
405 /*!
406  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
407  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
408  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
409  * Useful for python users.
410  */
411 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
412 {
413   if(!checkConsecutiveCellTypes())
414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
415   return new MEDCouplingUMeshCellByTypeEntry(this);
416 }
417
418 /*!
419  * Returns a set of all cell types available in \a this mesh.
420  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
421  * \warning this method does not throw any exception even if \a this is not defined.
422  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
423  */
424 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
425 {
426   return _types;
427 }
428
429 /*!
430  * This method returns the sorted list of geometric types in \a this.
431  * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
432  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
433  *
434  * \throw if connectivity in \a this is not correctly defined.
435  *  
436  * \sa MEDCouplingMesh::getAllGeoTypes
437  */
438 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
439 {
440   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
441   checkConnectivityFullyDefined();
442   int nbOfCells(getNumberOfCells());
443   if(nbOfCells==0)
444     return ret;
445   if(getMeshLength()<1)
446     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
447   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
448   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
449   for(int i=1;i<nbOfCells;i++,ci++)
450     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
451       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
452   return ret;
453 }
454
455 /*!
456  * This method is a method that compares \a this and \a other.
457  * This method compares \b all attributes, even names and component names.
458  */
459 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
460 {
461   if(!other)
462     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
463   std::ostringstream oss; oss.precision(15);
464   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
465   if(!otherC)
466     {
467       reason="mesh given in input is not castable in MEDCouplingUMesh !";
468       return false;
469     }
470   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
471     return false;
472   if(_mesh_dim!=otherC->_mesh_dim)
473     {
474       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
475       reason=oss.str();
476       return false;
477     }
478   if(_types!=otherC->_types)
479     {
480       oss << "umesh geometric type mismatch :\nThis geometric types are :";
481       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
482         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
483       oss << "\nOther geometric types are :";
484       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
485         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
486       reason=oss.str();
487       return false;
488     }
489   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
490     if(_nodal_connec==0 || otherC->_nodal_connec==0)
491       {
492         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
493         return false;
494       }
495   if(_nodal_connec!=otherC->_nodal_connec)
496     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
497       {
498         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
499         return false;
500       }
501   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
502     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
503       {
504         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
505         return false;
506       }
507   if(_nodal_connec_index!=otherC->_nodal_connec_index)
508     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
509       {
510         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
511         return false;
512       }
513   return true;
514 }
515
516 /*!
517  * Checks if data arrays of this mesh (node coordinates, nodal
518  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
519  * not considered.
520  *  \param [in] other - the mesh to compare with.
521  *  \param [in] prec - precision value used to compare node coordinates.
522  *  \return bool - \a true if the two meshes are same.
523  */
524 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
525 {
526   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
527   if(!otherC)
528     return false;
529   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
530     return false;
531   if(_mesh_dim!=otherC->_mesh_dim)
532     return false;
533   if(_types!=otherC->_types)
534     return false;
535   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
536     if(_nodal_connec==0 || otherC->_nodal_connec==0)
537       return false;
538   if(_nodal_connec!=otherC->_nodal_connec)
539     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
540       return false;
541   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
542     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
543       return false;
544   if(_nodal_connec_index!=otherC->_nodal_connec_index)
545     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
546       return false;
547   return true;
548 }
549
550 /*!
551  * Checks if \a this and \a other meshes are geometrically equivalent with high
552  * probability, else an exception is thrown. The meshes are considered equivalent if
553  * (1) meshes contain the same number of nodes and the same number of elements of the
554  * same types (2) three cells of the two meshes (first, last and middle) are based
555  * on coincident nodes (with a specified precision).
556  *  \param [in] other - the mesh to compare with.
557  *  \param [in] prec - the precision used to compare nodes of the two meshes.
558  *  \throw If the two meshes do not match.
559  */
560 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
561 {
562  MEDCouplingPointSet::checkFastEquivalWith(other,prec);
563  const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
564   if(!otherC)
565     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
566 }
567
568 /*!
569  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
570  * cells each node belongs to.
571  * \warning For speed reasons, this method does not check if node ids in the nodal
572  *          connectivity correspond to the size of node coordinates array.
573  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
574  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
575  *        dividing cell ids in \a revNodal into groups each referring to one
576  *        node. Its every element (except the last one) is an index pointing to the
577  *         first id of a group of cells. For example cells sharing the node #1 are 
578  *        described by following range of indices: 
579  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
580  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
581  *        Number of cells sharing the *i*-th node is
582  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
583  * \throw If the coordinates array is not set.
584  * \throw If the nodal connectivity of cells is not defined.
585  * 
586  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
587  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
588  */
589 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
590 {
591   checkFullyDefined();
592   int nbOfNodes=getNumberOfNodes();
593   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
594   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
595   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
596   const int *conn=_nodal_connec->getConstPointer();
597   const int *connIndex=_nodal_connec_index->getConstPointer();
598   int nbOfCells=getNumberOfCells();
599   int nbOfEltsInRevNodal=0;
600   for(int eltId=0;eltId<nbOfCells;eltId++)
601     {
602       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
603       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
604       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
605         if(*iter>=0)//for polyhedrons
606           {
607             nbOfEltsInRevNodal++;
608             revNodalIndxPtr[(*iter)+1]++;
609           }
610     }
611   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
612   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
613   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
614   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
615   for(int eltId=0;eltId<nbOfCells;eltId++)
616     {
617       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
618       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
619       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
620         if(*iter>=0)//for polyhedrons
621           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
622     }
623 }
624
625 /// @cond INTERNAL
626
627 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
628 {
629   return id;
630 }
631
632 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
633 {
634   if(!compute)
635     return id+1;
636   else
637     {
638       if(cm.getOrientationStatus(nb,conn1,conn2))
639         return id+1;
640       else
641         return -(id+1);
642     }
643 }
644
645 class MinusOneSonsGenerator
646 {
647 public:
648   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
649   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
650   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
651   static const int DELTA=1;
652 private:
653   const INTERP_KERNEL::CellModel& _cm;
654 };
655
656 class MinusOneSonsGeneratorBiQuadratic
657 {
658 public:
659   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
660   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
661   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
662   static const int DELTA=1;
663 private:
664   const INTERP_KERNEL::CellModel& _cm;
665 };
666
667 class MinusTwoSonsGenerator
668 {
669 public:
670   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
671   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
672   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
673   static const int DELTA=2;
674 private:
675   const INTERP_KERNEL::CellModel& _cm;
676 };
677
678 /// @endcond
679
680 /*!
681  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
682  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
683  * describing correspondence between cells of \a this and the result meshes are
684  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
685  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
686  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
687  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
688  * \warning For speed reasons, this method does not check if node ids in the nodal
689  *          connectivity correspond to the size of node coordinates array.
690  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
691  *          to write this mesh to the MED file, its cells must be sorted using
692  *          sortCellsInMEDFileFrmt().
693  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
694  *         each cell of \a this mesh.
695  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
696  *        dividing cell ids in \a desc into groups each referring to one
697  *        cell of \a this mesh. Its every element (except the last one) is an index
698  *        pointing to the first id of a group of cells. For example cells of the
699  *        result mesh bounding the cell #1 of \a this mesh are described by following
700  *        range of indices:
701  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
702  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
703  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
704  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
705  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
706  *         by each cell of the result mesh.
707  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
708  *        in the result mesh,
709  *        dividing cell ids in \a revDesc into groups each referring to one
710  *        cell of the result mesh the same way as \a descIndx divides \a desc.
711  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
712  *        delete this mesh using decrRef() as it is no more needed.
713  *  \throw If the coordinates array is not set.
714  *  \throw If the nodal connectivity of cells is node defined.
715  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
716  *         revDescIndx == NULL.
717  * 
718  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
719  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
720  * \sa buildDescendingConnectivity2()
721  */
722 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
723 {
724   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
725 }
726
727 /*!
728  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
729  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
730  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
731  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
732  * \sa MEDCouplingUMesh::buildDescendingConnectivity
733  */
734 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
735 {
736   checkFullyDefined();
737   if(getMeshDimension()!=3)
738     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
739   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
740 }
741
742 /*!
743  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
744  * this->getMeshDimension(), that bound cells of \a this mesh. In
745  * addition arrays describing correspondence between cells of \a this and the result
746  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
747  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
748  *  mesh. This method differs from buildDescendingConnectivity() in that apart
749  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
750  * result meshes. So a positive id means that order of nodes in corresponding cells
751  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
752  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
753  * i.e. cell ids are one-based.
754  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
755  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
756  * \warning For speed reasons, this method does not check if node ids in the nodal
757  *          connectivity correspond to the size of node coordinates array.
758  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
759  *          to write this mesh to the MED file, its cells must be sorted using
760  *          sortCellsInMEDFileFrmt().
761  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
762  *         each cell of \a this mesh.
763  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
764  *        dividing cell ids in \a desc into groups each referring to one
765  *        cell of \a this mesh. Its every element (except the last one) is an index
766  *        pointing to the first id of a group of cells. For example cells of the
767  *        result mesh bounding the cell #1 of \a this mesh are described by following
768  *        range of indices:
769  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
770  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
771  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
772  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
773  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
774  *         by each cell of the result mesh.
775  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
776  *        in the result mesh,
777  *        dividing cell ids in \a revDesc into groups each referring to one
778  *        cell of the result mesh the same way as \a descIndx divides \a desc.
779  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
780  *        shares the node coordinates array with \a this mesh. The caller is to
781  *        delete this mesh using decrRef() as it is no more needed.
782  *  \throw If the coordinates array is not set.
783  *  \throw If the nodal connectivity of cells is node defined.
784  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
785  *         revDescIndx == NULL.
786  * 
787  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
788  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
789  * \sa buildDescendingConnectivity()
790  */
791 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
792 {
793   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
794 }
795
796 /*!
797  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
798  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
799  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
800  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
801  *
802  * \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
803  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
804  * \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.
805  */
806 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
807 {
808   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
809   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
810   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
811   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
812   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
813   meshDM1=0;
814   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
815 }
816
817 /*!
818  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
819  * 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,
820  * excluding a set of meshdim-1 cells in input descending connectivity.
821  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
822  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
823  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
824  *
825  * \param [in] desc descending connectivity array.
826  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
827  * \param [in] revDesc reverse descending connectivity array.
828  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
829  * \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
830  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
831  * \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.
832  */
833 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
834                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
835 {
836   if(!desc || !descIndx || !revDesc || !revDescIndx)
837     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
838   const int *descPtr=desc->getConstPointer();
839   const int *descIPtr=descIndx->getConstPointer();
840   const int *revDescPtr=revDesc->getConstPointer();
841   const int *revDescIPtr=revDescIndx->getConstPointer();
842   //
843   int nbCells=descIndx->getNumberOfTuples()-1;
844   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
845   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
846   int *out1Ptr=out1->getPointer();
847   *out1Ptr++=0;
848   out0->reserve(desc->getNumberOfTuples());
849   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
850     {
851       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
852         {
853           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
854           s.erase(i);
855           out0->insertAtTheEnd(s.begin(),s.end());
856         }
857       *out1Ptr=out0->getNumberOfTuples();
858     }
859   neighbors=out0.retn();
860   neighborsIndx=out1.retn();
861 }
862
863 /// @cond INTERNAL
864
865 /*!
866  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
867  * For speed reasons no check of this will be done.
868  */
869 template<class SonsGenerator>
870 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
871 {
872   if(!desc || !descIndx || !revDesc || !revDescIndx)
873     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
874   checkConnectivityFullyDefined();
875   int nbOfCells=getNumberOfCells();
876   int nbOfNodes=getNumberOfNodes();
877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
878   int *revNodalIndxPtr=revNodalIndx->getPointer();
879   const int *conn=_nodal_connec->getConstPointer();
880   const int *connIndex=_nodal_connec_index->getConstPointer();
881   std::string name="Mesh constituent of "; name+=getName();
882   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
883   ret->setCoords(getCoords());
884   ret->allocateCells(2*nbOfCells);
885   descIndx->alloc(nbOfCells+1,1);
886   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
887   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
888   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
889     {
890       int pos=connIndex[eltId];
891       int posP1=connIndex[eltId+1];
892       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
893       SonsGenerator sg(cm);
894       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
895       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
896       for(unsigned i=0;i<nbOfSons;i++)
897         {
898           INTERP_KERNEL::NormalizedCellType cmsId;
899           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
900           for(unsigned k=0;k<nbOfNodesSon;k++)
901             if(tmp[k]>=0)
902               revNodalIndxPtr[tmp[k]+1]++;
903           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
904           revDesc2->pushBackSilent(eltId);
905         }
906       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
907     }
908   int nbOfCellsM1=ret->getNumberOfCells();
909   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
910   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
911   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
912   int *revNodalPtr=revNodal->getPointer();
913   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
914   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
915   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
916     {
917       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
918       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
919       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
920         if(*iter>=0)//for polyhedrons
921           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
922     }
923   //
924   DataArrayInt *commonCells=0,*commonCellsI=0;
925   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
926   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
927   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
928   int newNbOfCellsM1=-1;
929   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
930                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
931   std::vector<bool> isImpacted(nbOfCellsM1,false);
932   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
933     for(int work2=work[0];work2!=work[1];work2++)
934       isImpacted[commonCellsPtr[work2]]=true;
935   const int *o2nM1Ptr=o2nM1->getConstPointer();
936   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
937   const int *n2oM1Ptr=n2oM1->getConstPointer();
938   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
939   ret2->copyTinyInfoFrom(this);
940   desc->alloc(descIndx->back(),1);
941   int *descPtr=desc->getPointer();
942   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
943   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
944     {
945       if(!isImpacted[i])
946         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
947       else
948         {
949           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
950             {
951               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
952               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
953             }
954           else
955             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
956         }
957     }
958   revDesc->reserve(newNbOfCellsM1);
959   revDescIndx->alloc(newNbOfCellsM1+1,1);
960   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
961   const int *revDesc2Ptr=revDesc2->getConstPointer();
962   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
963     {
964       int oldCellIdM1=n2oM1Ptr[i];
965       if(!isImpacted[oldCellIdM1])
966         {
967           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
968           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
969         }
970       else
971         {
972           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
973             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
974           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
975           commonCellsIPtr++;
976         }
977     }
978   //
979   return ret2.retn();
980 }
981
982 struct MEDCouplingAccVisit
983 {
984   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
985   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
986   int _new_nb_of_nodes;
987 };
988
989 /// @endcond
990
991 /*!
992  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
993  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
994  * array of cell ids. Pay attention that after conversion all algorithms work slower
995  * with \a this mesh than before conversion. <br> If an exception is thrown during the
996  * conversion due presence of invalid ids in the array of cells to convert, as a
997  * result \a this mesh contains some already converted elements. In this case the 2D
998  * mesh remains valid but 3D mesh becomes \b inconsistent!
999  *  \warning This method can significantly modify the order of geometric types in \a this,
1000  *          hence, to write this mesh to the MED file, its cells must be sorted using
1001  *          sortCellsInMEDFileFrmt().
1002  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1003  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1004  *         cellIdsToConvertBg.
1005  *  \throw If the coordinates array is not set.
1006  *  \throw If the nodal connectivity of cells is node defined.
1007  *  \throw If dimension of \a this mesh is not either 2 or 3.
1008  *
1009  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1010  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1011  */
1012 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1013 {
1014   checkFullyDefined();
1015   int dim=getMeshDimension();
1016   if(dim<2 || dim>3)
1017     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1018   int nbOfCells(getNumberOfCells());
1019   if(dim==2)
1020     {
1021       const int *connIndex=_nodal_connec_index->getConstPointer();
1022       int *conn=_nodal_connec->getPointer();
1023       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1024         {
1025           if(*iter>=0 && *iter<nbOfCells)
1026             {
1027               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1028               if(!cm.isQuadratic())
1029                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1030               else
1031                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1032             }
1033           else
1034             {
1035               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1036               oss << " in range [0," << nbOfCells << ") !";
1037               throw INTERP_KERNEL::Exception(oss.str().c_str());
1038             }
1039         }
1040     }
1041   else
1042     {
1043       int *connIndex=_nodal_connec_index->getPointer();
1044       int connIndexLgth=_nodal_connec_index->getNbOfElems();
1045       const int *connOld=_nodal_connec->getConstPointer();
1046       int connOldLgth=_nodal_connec->getNbOfElems();
1047       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1048       std::vector<bool> toBeDone(nbOfCells,false);
1049       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1050         {
1051           if(*iter>=0 && *iter<nbOfCells)
1052             toBeDone[*iter]=true;
1053           else
1054             {
1055               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1056               oss << " in range [0," << nbOfCells << ") !";
1057               throw INTERP_KERNEL::Exception(oss.str().c_str());
1058             }
1059         }
1060       for(int cellId=0;cellId<nbOfCells;cellId++)
1061         {
1062           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1063           int lgthOld(posP1-pos-1);
1064           if(toBeDone[cellId])
1065             {
1066               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1067               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1068               int *tmp(new int[nbOfFaces*lgthOld+1]);
1069               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1070               for(unsigned j=0;j<nbOfFaces;j++)
1071                 {
1072                   INTERP_KERNEL::NormalizedCellType type;
1073                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1074                   work+=offset;
1075                   *work++=-1;
1076                 }
1077               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1078               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1079               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1080               delete [] tmp;
1081             }
1082           else
1083             {
1084               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1085               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1086             }
1087         }
1088       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1089     }
1090   computeTypes();
1091 }
1092
1093 /*!
1094  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1095  * polyhedrons (if \a this is a 3D mesh).
1096  *  \warning As this method is purely for user-friendliness and no optimization is
1097  *          done to avoid construction of a useless vector, this method can be costly
1098  *          in memory.
1099  *  \throw If the coordinates array is not set.
1100  *  \throw If the nodal connectivity of cells is node defined.
1101  *  \throw If dimension of \a this mesh is not either 2 or 3.
1102  */
1103 void MEDCouplingUMesh::convertAllToPoly()
1104 {
1105   int nbOfCells=getNumberOfCells();
1106   std::vector<int> cellIds(nbOfCells);
1107   for(int i=0;i<nbOfCells;i++)
1108     cellIds[i]=i;
1109   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1110 }
1111
1112 /*!
1113  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1114  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1115  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1116  * base facet of the volume and the second half of nodes describes an opposite facet
1117  * having the same number of nodes as the base one. This method converts such
1118  * connectivity to a valid polyhedral format where connectivity of each facet is
1119  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1120  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1121  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1122  * a correct orientation of the first facet of a polyhedron, else orientation of a
1123  * corrected cell is reverse.<br>
1124  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1125  * it releases the user from boring description of polyhedra connectivity in the valid
1126  * format.
1127  *  \throw If \a this->getMeshDimension() != 3.
1128  *  \throw If \a this->getSpaceDimension() != 3.
1129  *  \throw If the nodal connectivity of cells is not defined.
1130  *  \throw If the coordinates array is not set.
1131  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1132  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1133  *
1134  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1135  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1136  */
1137 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1138 {
1139   checkFullyDefined();
1140   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1141     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1142   int nbOfCells=getNumberOfCells();
1143   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1144   newCi->alloc(nbOfCells+1,1);
1145   int *newci=newCi->getPointer();
1146   const int *ci=_nodal_connec_index->getConstPointer();
1147   const int *c=_nodal_connec->getConstPointer();
1148   newci[0]=0;
1149   for(int i=0;i<nbOfCells;i++)
1150     {
1151       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1152       if(type==INTERP_KERNEL::NORM_POLYHED)
1153         {
1154           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1155             {
1156               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1157               throw INTERP_KERNEL::Exception(oss.str().c_str());
1158             }
1159           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1160           if(n2%2!=0)
1161             {
1162               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 !";
1163               throw INTERP_KERNEL::Exception(oss.str().c_str());
1164             }
1165           int n1=(int)(n2/2);
1166           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)
1167         }
1168       else
1169         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1170     }
1171   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1172   newC->alloc(newci[nbOfCells],1);
1173   int *newc=newC->getPointer();
1174   for(int i=0;i<nbOfCells;i++)
1175     {
1176       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1177       if(type==INTERP_KERNEL::NORM_POLYHED)
1178         {
1179           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1180           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1181           *newc++=-1;
1182           for(std::size_t j=0;j<n1;j++)
1183             {
1184               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1185               newc[n1+5*j]=-1;
1186               newc[n1+5*j+1]=c[ci[i]+1+j];
1187               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1188               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1189               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1190             }
1191           newc+=n1*6;
1192         }
1193       else
1194         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1195     }
1196   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1197   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1198 }
1199
1200
1201 /*!
1202  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1203  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1204  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1205  *          to write this mesh to the MED file, its cells must be sorted using
1206  *          sortCellsInMEDFileFrmt().
1207  * \return \c true if at least one cell has been converted, \c false else. In the
1208  *         last case the nodal connectivity remains unchanged.
1209  * \throw If the coordinates array is not set.
1210  * \throw If the nodal connectivity of cells is not defined.
1211  * \throw If \a this->getMeshDimension() < 0.
1212  */
1213 bool MEDCouplingUMesh::unPolyze()
1214 {
1215   checkFullyDefined();
1216   int mdim=getMeshDimension();
1217   if(mdim<0)
1218     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1219   if(mdim<=1)
1220     return false;
1221   int nbOfCells=getNumberOfCells();
1222   if(nbOfCells<1)
1223     return false;
1224   int initMeshLgth=getMeshLength();
1225   int *conn=_nodal_connec->getPointer();
1226   int *index=_nodal_connec_index->getPointer();
1227   int posOfCurCell=0;
1228   int newPos=0;
1229   int lgthOfCurCell;
1230   bool ret=false;
1231   for(int i=0;i<nbOfCells;i++)
1232     {
1233       lgthOfCurCell=index[i+1]-posOfCurCell;
1234       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1235       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1236       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1237       int newLgth;
1238       if(cm.isDynamic())
1239         {
1240           switch(cm.getDimension())
1241             {
1242             case 2:
1243               {
1244                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1245                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1246                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1247                 break;
1248               }
1249             case 3:
1250               {
1251                 int nbOfFaces,lgthOfPolyhConn;
1252                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1253                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1254                 break;
1255               }
1256             case 1:
1257               {
1258                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1259                 break;
1260               }
1261             }
1262           ret=ret || (newType!=type);
1263           conn[newPos]=newType;
1264           newPos+=newLgth+1;
1265           posOfCurCell=index[i+1];
1266           index[i+1]=newPos;
1267         }
1268       else
1269         {
1270           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1271           newPos+=lgthOfCurCell;
1272           posOfCurCell+=lgthOfCurCell;
1273           index[i+1]=newPos;
1274         }
1275     }
1276   if(newPos!=initMeshLgth)
1277     _nodal_connec->reAlloc(newPos);
1278   if(ret)
1279     computeTypes();
1280   return ret;
1281 }
1282
1283 /*!
1284  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1285  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1286  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1287  *
1288  * \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 
1289  *             precision.
1290  */
1291 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1292 {
1293   checkFullyDefined();
1294   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1295     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1296   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1297   coords->recenterForMaxPrecision(eps);
1298   //
1299   int nbOfCells=getNumberOfCells();
1300   const int *conn=_nodal_connec->getConstPointer();
1301   const int *index=_nodal_connec_index->getConstPointer();
1302   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1303   connINew->alloc(nbOfCells+1,1);
1304   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1305   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1306   bool changed=false;
1307   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1308     {
1309       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1310         {
1311           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1312           changed=true;
1313         }
1314       else
1315         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1316       *connINewPtr=connNew->getNumberOfTuples();
1317     }
1318   if(changed)
1319     setConnectivity(connNew,connINew,false);
1320 }
1321
1322 /*!
1323  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1324  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1325  * the format of returned DataArrayInt instance.
1326  * 
1327  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1328  * \sa MEDCouplingUMesh::getNodeIdsInUse
1329  */
1330 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1331 {
1332   checkConnectivityFullyDefined();
1333   int nbOfCells=getNumberOfCells();
1334   const int *connIndex=_nodal_connec_index->getConstPointer();
1335   const int *conn=_nodal_connec->getConstPointer();
1336   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1337   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1338   std::vector<bool> retS(maxElt,false);
1339   for(int i=0;i<nbOfCells;i++)
1340     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1341       if(conn[j]>=0)
1342         retS[conn[j]]=true;
1343   int sz=0;
1344   for(int i=0;i<maxElt;i++)
1345     if(retS[i])
1346       sz++;
1347   DataArrayInt *ret=DataArrayInt::New();
1348   ret->alloc(sz,1);
1349   int *retPtr=ret->getPointer();
1350   for(int i=0;i<maxElt;i++)
1351     if(retS[i])
1352       *retPtr++=i;
1353   return ret;
1354 }
1355
1356 /*!
1357  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1358  * \sa MEDCouplingUMesh::getNodeIdsInUse
1359  */
1360 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1361 {
1362   int nbOfNodes=(int)nodeIdsInUse.size();
1363   int nbOfCells=getNumberOfCells();
1364   const int *connIndex=_nodal_connec_index->getConstPointer();
1365   const int *conn=_nodal_connec->getConstPointer();
1366   for(int i=0;i<nbOfCells;i++)
1367     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1368       if(conn[j]>=0)
1369         {
1370           if(conn[j]<nbOfNodes)
1371             nodeIdsInUse[conn[j]]=true;
1372           else
1373             {
1374               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1375               throw INTERP_KERNEL::Exception(oss.str().c_str());
1376             }
1377         }
1378 }
1379
1380 /*!
1381  * Finds nodes not used in any cell and returns an array giving a new id to every node
1382  * by excluding the unused nodes, for which the array holds -1. The result array is
1383  * a mapping in "Old to New" mode. 
1384  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1385  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1386  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1387  *          if the node is unused or a new id else. The caller is to delete this
1388  *          array using decrRef() as it is no more needed.  
1389  *  \throw If the coordinates array is not set.
1390  *  \throw If the nodal connectivity of cells is not defined.
1391  *  \throw If the nodal connectivity includes an invalid id.
1392  *
1393  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1394  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1395  * \sa computeNodeIdsAlg()
1396  */
1397 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1398 {
1399   nbrOfNodesInUse=-1;
1400   int nbOfNodes=getNumberOfNodes();
1401   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1402   ret->alloc(nbOfNodes,1);
1403   int *traducer=ret->getPointer();
1404   std::fill(traducer,traducer+nbOfNodes,-1);
1405   int nbOfCells=getNumberOfCells();
1406   const int *connIndex=_nodal_connec_index->getConstPointer();
1407   const int *conn=_nodal_connec->getConstPointer();
1408   for(int i=0;i<nbOfCells;i++)
1409     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1410       if(conn[j]>=0)
1411         {
1412           if(conn[j]<nbOfNodes)
1413             traducer[conn[j]]=1;
1414           else
1415             {
1416               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1417               throw INTERP_KERNEL::Exception(oss.str().c_str());
1418             }
1419         }
1420   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1421   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1422   return ret.retn();
1423 }
1424
1425 /*!
1426  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1427  * For each cell in \b this the number of nodes constituting cell is computed.
1428  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1429  * So for pohyhedrons some nodes can be counted several times in the returned result.
1430  * 
1431  * \return a newly allocated array
1432  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1433  */
1434 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1435 {
1436   checkConnectivityFullyDefined();
1437   int nbOfCells=getNumberOfCells();
1438   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1439   ret->alloc(nbOfCells,1);
1440   int *retPtr=ret->getPointer();
1441   const int *conn=getNodalConnectivity()->getConstPointer();
1442   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1443   for(int i=0;i<nbOfCells;i++,retPtr++)
1444     {
1445       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1446         *retPtr=connI[i+1]-connI[i]-1;
1447       else
1448         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1449     }
1450   return ret.retn();
1451 }
1452
1453 /*!
1454  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1455  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1456  *
1457  * \return DataArrayInt * - new object to be deallocated by the caller.
1458  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1459  */
1460 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1461 {
1462   checkConnectivityFullyDefined();
1463   int nbOfCells=getNumberOfCells();
1464   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1465   ret->alloc(nbOfCells,1);
1466   int *retPtr=ret->getPointer();
1467   const int *conn=getNodalConnectivity()->getConstPointer();
1468   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1469   for(int i=0;i<nbOfCells;i++,retPtr++)
1470     {
1471       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1472       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1473         *retPtr=(int)s.size();
1474       else
1475         {
1476           s.erase(-1);
1477           *retPtr=(int)s.size();
1478         }
1479     }
1480   return ret.retn();
1481 }
1482
1483 /*!
1484  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1485  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1486  * 
1487  * \return a newly allocated array
1488  */
1489 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1490 {
1491   checkConnectivityFullyDefined();
1492   int nbOfCells=getNumberOfCells();
1493   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1494   ret->alloc(nbOfCells,1);
1495   int *retPtr=ret->getPointer();
1496   const int *conn=getNodalConnectivity()->getConstPointer();
1497   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1498   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1499     {
1500       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1501       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1502     }
1503   return ret.retn();
1504 }
1505
1506 /*!
1507  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1508  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1509  * array mean that the corresponding old node is no more used. 
1510  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1511  *           this->getNumberOfNodes() before call of this method. The caller is to
1512  *           delete this array using decrRef() as it is no more needed. 
1513  *  \throw If the coordinates array is not set.
1514  *  \throw If the nodal connectivity of cells is not defined.
1515  *  \throw If the nodal connectivity includes an invalid id.
1516  *
1517  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1518  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1519  */
1520 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1521 {
1522   return MEDCouplingPointSet::zipCoordsTraducer();
1523 }
1524
1525 /*!
1526  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1527  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1528  */
1529 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1530 {
1531   switch(compType)
1532     {
1533     case 0:
1534       return AreCellsEqual0(conn,connI,cell1,cell2);
1535     case 1:
1536       return AreCellsEqual1(conn,connI,cell1,cell2);
1537     case 2:
1538       return AreCellsEqual2(conn,connI,cell1,cell2);
1539     case 3:
1540       return AreCellsEqual3(conn,connI,cell1,cell2);
1541     case 7:
1542       return AreCellsEqual7(conn,connI,cell1,cell2);
1543     }
1544   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1545 }
1546
1547 /*!
1548  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1549  */
1550 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1551 {
1552   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1553     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1554   return 0;
1555 }
1556
1557 /*!
1558  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1559  */
1560 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1561 {
1562   int sz=connI[cell1+1]-connI[cell1];
1563   if(sz==connI[cell2+1]-connI[cell2])
1564     {
1565       if(conn[connI[cell1]]==conn[connI[cell2]])
1566         {
1567           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1568           unsigned dim=cm.getDimension();
1569           if(dim!=3)
1570             {
1571               if(dim!=1)
1572                 {
1573                   int sz1=2*(sz-1);
1574                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1575                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1576                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1577                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1578                   return work!=tmp+sz1?1:0;
1579                 }
1580               else
1581                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1582             }
1583           else
1584             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1585         }
1586     }
1587   return 0;
1588 }
1589
1590 /*!
1591  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1592  */
1593 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1594 {
1595   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1596     {
1597       if(conn[connI[cell1]]==conn[connI[cell2]])
1598         {
1599           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1600           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1601           return s1==s2?1:0;
1602         }
1603     }
1604   return 0;
1605 }
1606
1607 /*!
1608  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1609  */
1610 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1611 {
1612   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1613     {
1614       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1615       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1616       return s1==s2?1:0;
1617     }
1618   return 0;
1619 }
1620
1621 /*!
1622  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1623  */
1624 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1625 {
1626   int sz=connI[cell1+1]-connI[cell1];
1627   if(sz==connI[cell2+1]-connI[cell2])
1628     {
1629       if(conn[connI[cell1]]==conn[connI[cell2]])
1630         {
1631           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1632           unsigned dim=cm.getDimension();
1633           if(dim!=3)
1634             {
1635               if(dim!=1)
1636                 {
1637                   int sz1=2*(sz-1);
1638                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1639                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1640                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1641                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1642                   if(work!=tmp+sz1)
1643                     return 1;
1644                   else
1645                     {
1646                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1647                       std::reverse_iterator<int *> it2((int *)tmp);
1648                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1649                         return 2;
1650                       else
1651                         return 0;
1652                     }
1653                   
1654                   return work!=tmp+sz1?1:0;
1655                 }
1656               else
1657                 {//case of SEG2 and SEG3
1658                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1659                     return 1;
1660                   if(!cm.isQuadratic())
1661                     {
1662                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1663                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1664                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1665                         return 2;
1666                       return 0;
1667                     }
1668                   else
1669                     {
1670                       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])
1671                         return 2;
1672                       return 0;
1673                     }
1674                 }
1675             }
1676           else
1677             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1678         }
1679     }
1680   return 0;
1681 }
1682
1683 /*!
1684  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1685  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1686  * and result remains unchanged.
1687  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1688  * If in 'candidates' pool -1 value is considered as an empty value.
1689  * WARNING this method returns only ONE set of result !
1690  */
1691 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1692 {
1693   if(candidates.size()<1)
1694     return false;
1695   bool ret=false;
1696   std::vector<int>::const_iterator iter=candidates.begin();
1697   int start=(*iter++);
1698   for(;iter!=candidates.end();iter++)
1699     {
1700       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1701       if(status!=0)
1702         {
1703           if(!ret)
1704             {
1705               result->pushBackSilent(start);
1706               ret=true;
1707             }
1708           if(status==1)
1709             result->pushBackSilent(*iter);
1710           else
1711             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1712         }
1713     }
1714   return ret;
1715 }
1716
1717 /*!
1718  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1719  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1720  *
1721  * \param [in] compType input specifying the technique used to compare cells each other.
1722  *   - 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.
1723  *   - 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)
1724  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1725  *   - 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
1726  * can be used for users not sensitive to orientation of cell
1727  * \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.
1728  * \param [out] commonCells
1729  * \param [out] commonCellsI
1730  * \return the correspondance array old to new in a newly allocated array.
1731  * 
1732  */
1733 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1734 {
1735   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1736   getReverseNodalConnectivity(revNodal,revNodalI);
1737   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1738 }
1739
1740 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1741                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1742 {
1743   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1744   int nbOfCells=nodalI->getNumberOfTuples()-1;
1745   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1746   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1747   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1748   std::vector<bool> isFetched(nbOfCells,false);
1749   if(startCellId==0)
1750     {
1751       for(int i=0;i<nbOfCells;i++)
1752         {
1753           if(!isFetched[i])
1754             {
1755               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1756               std::vector<int> v,v2;
1757               if(connOfNode!=connPtr+connIPtr[i+1])
1758                 {
1759                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1760                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1761                   connOfNode++;
1762                 }
1763               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1764                 if(*connOfNode>=0)
1765                   {
1766                     v=v2;
1767                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1768                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1769                     v2.resize(std::distance(v2.begin(),it));
1770                   }
1771               if(v2.size()>1)
1772                 {
1773                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1774                     {
1775                       int pos=commonCellsI->back();
1776                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1777                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1778                         isFetched[*it]=true;
1779                     }
1780                 }
1781             }
1782         }
1783     }
1784   else
1785     {
1786       for(int i=startCellId;i<nbOfCells;i++)
1787         {
1788           if(!isFetched[i])
1789             {
1790               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1791               std::vector<int> v,v2;
1792               if(connOfNode!=connPtr+connIPtr[i+1])
1793                 {
1794                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1795                   connOfNode++;
1796                 }
1797               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1798                 if(*connOfNode>=0)
1799                   {
1800                     v=v2;
1801                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1802                     v2.resize(std::distance(v2.begin(),it));
1803                   }
1804               if(v2.size()>1)
1805                 {
1806                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1807                     {
1808                       int pos=commonCellsI->back();
1809                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1810                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1811                         isFetched[*it]=true;
1812                     }
1813                 }
1814             }
1815         }
1816     }
1817   commonCellsArr=commonCells.retn();
1818   commonCellsIArr=commonCellsI.retn();
1819 }
1820
1821 /*!
1822  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1823  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1824  * than \a other->getNumberOfCells() in the returned array means that there is no
1825  * corresponding cell in \a this mesh.
1826  * It is expected that \a this and \a other meshes share the same node coordinates
1827  * array, if it is not so an exception is thrown. 
1828  *  \param [in] other - the mesh to compare with.
1829  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1830  *         valid values [0,1,2], see zipConnectivityTraducer().
1831  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1832  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1833  *         values. The caller is to delete this array using
1834  *         decrRef() as it is no more needed.
1835  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1836  *         mesh.
1837  *
1838  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1839  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1840  *  \sa checkDeepEquivalOnSameNodesWith()
1841  *  \sa checkGeoEquivalWith()
1842  */
1843 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1844 {
1845   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1846   int nbOfCells=getNumberOfCells();
1847   static const int possibleCompType[]={0,1,2};
1848   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1849     {
1850       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1851       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1852       oss << " !";
1853       throw INTERP_KERNEL::Exception(oss.str().c_str());
1854     }
1855   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1856   arr=o2n->substr(nbOfCells);
1857   arr->setName(other->getName());
1858   int tmp;
1859   if(other->getNumberOfCells()==0)
1860     return true;
1861   return arr->getMaxValue(tmp)<nbOfCells;
1862 }
1863
1864 /*!
1865  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1866  * This method tries to determine if \b other is fully included in \b this.
1867  * The main difference is that this method is not expected to throw exception.
1868  * This method has two outputs :
1869  *
1870  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1871  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1872  */
1873 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1874 {
1875   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1876   DataArrayInt *commonCells=0,*commonCellsI=0;
1877   int thisNbCells=getNumberOfCells();
1878   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1879   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1880   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1881   int otherNbCells=other->getNumberOfCells();
1882   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1883   arr2->alloc(otherNbCells,1);
1884   arr2->fillWithZero();
1885   int *arr2Ptr=arr2->getPointer();
1886   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1887   for(int i=0;i<nbOfCommon;i++)
1888     {
1889       int start=commonCellsPtr[commonCellsIPtr[i]];
1890       if(start<thisNbCells)
1891         {
1892           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1893             {
1894               int sig=commonCellsPtr[j]>0?1:-1;
1895               int val=std::abs(commonCellsPtr[j])-1;
1896               if(val>=thisNbCells)
1897                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1898             }
1899         }
1900     }
1901   arr2->setName(other->getName());
1902   if(arr2->presenceOfValue(0))
1903     return false;
1904   arr=arr2.retn();
1905   return true;
1906 }
1907
1908 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1909 {
1910   if(!other)
1911     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1912   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1913   if(!otherC)
1914     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1915   std::vector<const MEDCouplingUMesh *> ms(2);
1916   ms[0]=this;
1917   ms[1]=otherC;
1918   return MergeUMeshesOnSameCoords(ms);
1919 }
1920
1921 /*!
1922  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1923  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1924  * cellIds is not given explicitely but by a range python like.
1925  * 
1926  * \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.
1927  * \return a newly allocated
1928  * 
1929  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1930  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1931  */
1932 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
1933 {
1934   if(getMeshDimension()!=-1)
1935     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1936   else
1937     {
1938       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1939       if(newNbOfCells!=1)
1940         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1941       if(start!=0)
1942         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1943       incrRef();
1944       return const_cast<MEDCouplingUMesh *>(this);
1945     }
1946 }
1947
1948 /*!
1949  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1950  * The result mesh shares or not the node coordinates array with \a this mesh depending
1951  * on \a keepCoords parameter.
1952  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1953  *           to write this mesh to the MED file, its cells must be sorted using
1954  *           sortCellsInMEDFileFrmt().
1955  *  \param [in] begin - an array of cell ids to include to the new mesh.
1956  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1957  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1958  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1959  *         by calling zipCoords().
1960  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1961  *         to delete this mesh using decrRef() as it is no more needed. 
1962  *  \throw If the coordinates array is not set.
1963  *  \throw If the nodal connectivity of cells is not defined.
1964  *  \throw If any cell id in the array \a begin is not valid.
1965  *
1966  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1967  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1968  */
1969 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1970 {
1971   if(getMeshDimension()!=-1)
1972     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1973   else
1974     {
1975       if(end-begin!=1)
1976         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1977       if(begin[0]!=0)
1978         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1979       incrRef();
1980       return const_cast<MEDCouplingUMesh *>(this);
1981     }
1982 }
1983
1984 /*!
1985  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1986  *
1987  * 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.
1988  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1989  * The number of cells of \b this will remain the same with this method.
1990  *
1991  * \param [in] begin begin of cell ids (included) of cells in this to assign
1992  * \param [in] end end of cell ids (excluded) of cells in this to assign
1993  * \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 ).
1994  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1995  */
1996 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
1997 {
1998   checkConnectivityFullyDefined();
1999   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2000   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2001     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2002   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2003     {
2004       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2005       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2006       throw INTERP_KERNEL::Exception(oss.str().c_str());
2007     }
2008   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2009   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2010     {
2011       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2012       throw INTERP_KERNEL::Exception(oss.str().c_str());
2013     }
2014   int nbOfCells=getNumberOfCells();
2015   bool easyAssign=true;
2016   const int *connI=_nodal_connec_index->getConstPointer();
2017   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2018   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2019     {
2020       if(*it>=0 && *it<nbOfCells)
2021         {
2022           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2023         }
2024       else
2025         {
2026           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2027           throw INTERP_KERNEL::Exception(oss.str().c_str());
2028         }
2029     }
2030   if(easyAssign)
2031     {
2032       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2033       computeTypes();
2034     }
2035   else
2036     {
2037       DataArrayInt *arrOut=0,*arrIOut=0;
2038       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2039                                                arrOut,arrIOut);
2040       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2041       setConnectivity(arrOut,arrIOut,true);
2042     }
2043 }
2044
2045 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2046 {
2047   checkConnectivityFullyDefined();
2048   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2049   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2050     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2051   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2052     {
2053       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2054       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2055       throw INTERP_KERNEL::Exception(oss.str().c_str());
2056     }
2057   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2058   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2059     {
2060       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2061       throw INTERP_KERNEL::Exception(oss.str().c_str());
2062     }
2063   int nbOfCells=getNumberOfCells();
2064   bool easyAssign=true;
2065   const int *connI=_nodal_connec_index->getConstPointer();
2066   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2067   int it=start;
2068   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2069     {
2070       if(it>=0 && it<nbOfCells)
2071         {
2072           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2073         }
2074       else
2075         {
2076           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2077           throw INTERP_KERNEL::Exception(oss.str().c_str());
2078         }
2079     }
2080   if(easyAssign)
2081     {
2082       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2083       computeTypes();
2084     }
2085   else
2086     {
2087       DataArrayInt *arrOut=0,*arrIOut=0;
2088       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2089                                                 arrOut,arrIOut);
2090       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2091       setConnectivity(arrOut,arrIOut,true);
2092     }
2093 }                      
2094
2095 /*!
2096  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2097  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2098  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2099  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2100  *
2101  * \param [in] begin input start of array of node ids.
2102  * \param [in] end input end of array of node ids.
2103  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2104  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2105  */
2106 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2107 {
2108   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2109   checkConnectivityFullyDefined();
2110   int tmp=-1;
2111   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2112   std::vector<bool> fastFinder(sz,false);
2113   for(const int *work=begin;work!=end;work++)
2114     if(*work>=0 && *work<sz)
2115       fastFinder[*work]=true;
2116   int nbOfCells=getNumberOfCells();
2117   const int *conn=getNodalConnectivity()->getConstPointer();
2118   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2119   for(int i=0;i<nbOfCells;i++)
2120     {
2121       int ref=0,nbOfHit=0;
2122       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2123         if(*work2>=0)
2124           {
2125             ref++;
2126             if(fastFinder[*work2])
2127               nbOfHit++;
2128           }
2129       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2130         cellIdsKept->pushBackSilent(i);
2131     }
2132   cellIdsKeptArr=cellIdsKept.retn();
2133 }
2134
2135 /*!
2136  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2137  * this->getMeshDimension(), that bound some cells of \a this mesh.
2138  * The cells of lower dimension to include to the result mesh are selected basing on
2139  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2140  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2141  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2142  * created mesh shares the node coordinates array with \a this mesh. 
2143  *  \param [in] begin - the array of node ids.
2144  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2145  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2146  *         array \a begin are added, else cells whose any node is in the
2147  *         array \a begin are added.
2148  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2149  *         to delete this mesh using decrRef() as it is no more needed. 
2150  *  \throw If the coordinates array is not set.
2151  *  \throw If the nodal connectivity of cells is not defined.
2152  *  \throw If any node id in \a begin is not valid.
2153  *
2154  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2155  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2156  */
2157 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2158 {
2159   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2160   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2161   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2162   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2163   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2164 }
2165
2166 /*!
2167  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2168  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2169  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2170  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2171  *         by calling zipCoords().
2172  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2173  *         to delete this mesh using decrRef() as it is no more needed. 
2174  *  \throw If the coordinates array is not set.
2175  *  \throw If the nodal connectivity of cells is not defined.
2176  *
2177  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2178  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2179  */
2180 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2181 {
2182   DataArrayInt *desc=DataArrayInt::New();
2183   DataArrayInt *descIndx=DataArrayInt::New();
2184   DataArrayInt *revDesc=DataArrayInt::New();
2185   DataArrayInt *revDescIndx=DataArrayInt::New();
2186   //
2187   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2188   revDesc->decrRef();
2189   desc->decrRef();
2190   descIndx->decrRef();
2191   int nbOfCells=meshDM1->getNumberOfCells();
2192   const int *revDescIndxC=revDescIndx->getConstPointer();
2193   std::vector<int> boundaryCells;
2194   for(int i=0;i<nbOfCells;i++)
2195     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2196       boundaryCells.push_back(i);
2197   revDescIndx->decrRef();
2198   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2199   return ret;
2200 }
2201
2202 /*!
2203  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2204  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2205  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2206  */
2207 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2208 {
2209   checkFullyDefined();
2210   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2211   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2212   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2213   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2214   //
2215   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2216   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2217   //
2218   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2219   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2220   const int *revDescPtr=revDesc->getConstPointer();
2221   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2222   int nbOfCells=getNumberOfCells();
2223   std::vector<bool> ret1(nbOfCells,false);
2224   int sz=0;
2225   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2226     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2227       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2228   //
2229   DataArrayInt *ret2=DataArrayInt::New();
2230   ret2->alloc(sz,1);
2231   int *ret2Ptr=ret2->getPointer();
2232   sz=0;
2233   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2234     if(*it)
2235       *ret2Ptr++=sz;
2236   ret2->setName("BoundaryCells");
2237   return ret2;
2238 }
2239
2240 /*!
2241  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2242  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2243  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2244  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2245  *
2246  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2247  * This method method returns cells ids set s = s1 + s2 where :
2248  * 
2249  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2250  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2251  *
2252  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2253  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2254  *
2255  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2256  * \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
2257  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2258  */
2259 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2260 {
2261   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2262     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2263   checkConnectivityFullyDefined();
2264   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2265   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2266     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2267   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2268   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2269   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2270   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2271   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2272   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2273   DataArrayInt *idsOtherInConsti=0;
2274   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2275   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2276   if(!b)
2277     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2278   std::set<int> s1;
2279   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2280     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2281   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2282   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2283   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2284   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2285   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2286   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2287   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2288   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2289   neighThisPartAuto=0;
2290   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2291   const int li[2]={0,1};
2292   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2293   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2294   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2295   s_renum1->sort();
2296   //
2297   cellIdsRk0=s0arr.retn();
2298   cellIdsRk1=s_renum1.retn();
2299 }
2300
2301 /*!
2302  * 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
2303  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2304  * 
2305  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2306  */
2307 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2308 {
2309   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2310   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2311   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2312   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2313   //
2314   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2315   revDesc=0; desc=0; descIndx=0;
2316   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2317   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2318   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2319 }
2320
2321 /*!
2322  * Finds nodes lying on the boundary of \a this mesh.
2323  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2324  *          nodes. The caller is to delete this array using decrRef() as it is no
2325  *          more needed.
2326  *  \throw If the coordinates array is not set.
2327  *  \throw If the nodal connectivity of cells is node defined.
2328  *
2329  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2330  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2331  */
2332 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2333 {
2334   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2335   return skin->computeFetchedNodeIds();
2336 }
2337
2338 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2339 {
2340   incrRef();
2341   return const_cast<MEDCouplingUMesh *>(this);
2342 }
2343
2344 /*!
2345  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2346  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2347  * 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.
2348  * 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.
2349  * 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.
2350  *
2351  * \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
2352  *             parameter is altered during the call.
2353  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2354  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2355  * \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.
2356  *
2357  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2358  */
2359 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2360                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2361 {
2362   checkFullyDefined();
2363   otherDimM1OnSameCoords.checkFullyDefined();
2364   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2365     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2366   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2367     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2368   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2369   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2370   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2371   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2372   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2373   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2374   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2375   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2376   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2377   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2378   //
2379   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2380   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2381   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2382   DataArrayInt *idsTmp=0;
2383   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2384   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2385   if(!b)
2386     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2387   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2388   DataArrayInt *tmp0=0,*tmp1=0;
2389   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2392   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2393   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2394   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2395   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2396   //
2397   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2398   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2399   nodeIdsToDuplicate=s3.retn();
2400 }
2401
2402 /*!
2403  * This method operates a modification of the connectivity and coords in \b this.
2404  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2405  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2406  * 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
2407  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2408  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2409  * 
2410  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2411  * 
2412  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2413  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2414  */
2415 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2416 {
2417   int nbOfNodes=getNumberOfNodes();
2418   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2419   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2420 }
2421
2422 /*!
2423  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2424  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2425  * This method is a generalization of shiftNodeNumbersInConn().
2426  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2427  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2428  *         this->getNumberOfNodes(), in "Old to New" mode. 
2429  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2430  *  \throw If the nodal connectivity of cells is not defined.
2431  *
2432  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2433  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2434  */
2435 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2436 {
2437   checkConnectivityFullyDefined();
2438   int *conn=getNodalConnectivity()->getPointer();
2439   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2440   int nbOfCells=getNumberOfCells();
2441   for(int i=0;i<nbOfCells;i++)
2442     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2443       {
2444         int& node=conn[iconn];
2445         if(node>=0)//avoid polyhedron separator
2446           {
2447             node=newNodeNumbersO2N[node];
2448           }
2449       }
2450   _nodal_connec->declareAsNew();
2451   updateTime();
2452 }
2453
2454 /*!
2455  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2456  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2457  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2458  * 
2459  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2460  */
2461 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2462 {
2463   checkConnectivityFullyDefined();
2464   int *conn=getNodalConnectivity()->getPointer();
2465   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2466   int nbOfCells=getNumberOfCells();
2467   for(int i=0;i<nbOfCells;i++)
2468     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2469       {
2470         int& node=conn[iconn];
2471         if(node>=0)//avoid polyhedron separator
2472           {
2473             node+=delta;
2474           }
2475       }
2476   _nodal_connec->declareAsNew();
2477   updateTime();
2478 }
2479
2480 /*!
2481  * This method operates a modification of the connectivity in \b this.
2482  * 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.
2483  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2484  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2485  * 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
2486  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2487  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2488  * 
2489  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2490  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2491  * 
2492  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2493  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2494  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2495  */
2496 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2497 {
2498   checkConnectivityFullyDefined();
2499   std::map<int,int> m;
2500   int val=offset;
2501   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2502     m[*work]=val;
2503   int *conn=getNodalConnectivity()->getPointer();
2504   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2505   int nbOfCells=getNumberOfCells();
2506   for(int i=0;i<nbOfCells;i++)
2507     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2508       {
2509         int& node=conn[iconn];
2510         if(node>=0)//avoid polyhedron separator
2511           {
2512             std::map<int,int>::iterator it=m.find(node);
2513             if(it!=m.end())
2514               node=(*it).second;
2515           }
2516       }
2517   updateTime();
2518 }
2519
2520 /*!
2521  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2522  *
2523  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2524  * After the call of this method the number of cells remains the same as before.
2525  *
2526  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2527  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2528  * be strictly in [0;this->getNumberOfCells()).
2529  *
2530  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2531  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2532  * should be contained in[0;this->getNumberOfCells()).
2533  * 
2534  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2535  */
2536 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2537 {
2538   checkConnectivityFullyDefined();
2539   int nbCells=getNumberOfCells();
2540   const int *array=old2NewBg;
2541   if(check)
2542     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2543   //
2544   const int *conn=_nodal_connec->getConstPointer();
2545   const int *connI=_nodal_connec_index->getConstPointer();
2546   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2547   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2548   const int *n2oPtr=n2o->begin();
2549   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2550   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2551   newConn->copyStringInfoFrom(*_nodal_connec);
2552   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2553   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2554   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2555   //
2556   int *newC=newConn->getPointer();
2557   int *newCI=newConnI->getPointer();
2558   int loc=0;
2559   newCI[0]=loc;
2560   for(int i=0;i<nbCells;i++)
2561     {
2562       int pos=n2oPtr[i];
2563       int nbOfElts=connI[pos+1]-connI[pos];
2564       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2565       loc+=nbOfElts;
2566       newCI[i+1]=loc;
2567     }
2568   //
2569   setConnectivity(newConn,newConnI);
2570   if(check)
2571     free(const_cast<int *>(array));
2572 }
2573
2574 /*!
2575  * Finds cells whose bounding boxes intersect a given bounding box.
2576  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2577  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2578  *         zMax (if in 3D). 
2579  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2580  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2581  *         extent of the bounding box of cell to produce an addition to this bounding box.
2582  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2583  *         cells. The caller is to delete this array using decrRef() as it is no more
2584  *         needed. 
2585  *  \throw If the coordinates array is not set.
2586  *  \throw If the nodal connectivity of cells is not defined.
2587  *
2588  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2589  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2590  */
2591 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2592 {
2593   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2594   if(getMeshDimension()==-1)
2595     {
2596       elems->pushBackSilent(0);
2597       return elems.retn();
2598     }
2599   int dim=getSpaceDimension();
2600   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2601   const int* conn      = getNodalConnectivity()->getConstPointer();
2602   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2603   const double* coords = getCoords()->getConstPointer();
2604   int nbOfCells=getNumberOfCells();
2605   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2606     {
2607       for (int i=0; i<dim; i++)
2608         {
2609           elem_bb[i*2]=std::numeric_limits<double>::max();
2610           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2611         }
2612
2613       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2614         {
2615           int node= conn[inode];
2616           if(node>=0)//avoid polyhedron separator
2617             {
2618               for (int idim=0; idim<dim; idim++)
2619                 {
2620                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2621                     {
2622                       elem_bb[idim*2] = coords[node*dim+idim] ;
2623                     }
2624                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2625                     {
2626                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2627                     }
2628                 }
2629             }
2630         }
2631       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2632         elems->pushBackSilent(ielem);
2633     }
2634   return elems.retn();
2635 }
2636
2637 /*!
2638  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2639  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2640  * added in 'elems' parameter.
2641  */
2642 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2643 {
2644   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2645   if(getMeshDimension()==-1)
2646     {
2647       elems->pushBackSilent(0);
2648       return elems.retn();
2649     }
2650   int dim=getSpaceDimension();
2651   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2652   const int* conn      = getNodalConnectivity()->getConstPointer();
2653   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2654   const double* coords = getCoords()->getConstPointer();
2655   int nbOfCells=getNumberOfCells();
2656   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2657     {
2658       for (int i=0; i<dim; i++)
2659         {
2660           elem_bb[i*2]=std::numeric_limits<double>::max();
2661           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2662         }
2663
2664       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2665         {
2666           int node= conn[inode];
2667           if(node>=0)//avoid polyhedron separator
2668             {
2669               for (int idim=0; idim<dim; idim++)
2670                 {
2671                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2672                     {
2673                       elem_bb[idim*2] = coords[node*dim+idim] ;
2674                     }
2675                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2676                     {
2677                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2678                     }
2679                 }
2680             }
2681         }
2682       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2683         elems->pushBackSilent(ielem);
2684     }
2685   return elems.retn();
2686 }
2687
2688 /*!
2689  * Returns a type of a cell by its id.
2690  *  \param [in] cellId - the id of the cell of interest.
2691  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2692  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2693  */
2694 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2695 {
2696   const int *ptI=_nodal_connec_index->getConstPointer();
2697   const int *pt=_nodal_connec->getConstPointer();
2698   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2699     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2700   else
2701     {
2702       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2703       throw INTERP_KERNEL::Exception(oss.str().c_str());
2704     }
2705 }
2706
2707 /*!
2708  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2709  * This method does not throw exception if geometric type \a type is not in \a this.
2710  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2711  * The coordinates array is not considered here.
2712  *
2713  * \param [in] type the geometric type
2714  * \return cell ids in this having geometric type \a type.
2715  */
2716 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2717 {
2718   
2719   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2720   ret->alloc(0,1);
2721   checkConnectivityFullyDefined();
2722   int nbCells=getNumberOfCells();
2723   int mdim=getMeshDimension();
2724   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2725   if(mdim!=(int)cm.getDimension())
2726     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2727   const int *ptI=_nodal_connec_index->getConstPointer();
2728   const int *pt=_nodal_connec->getConstPointer();
2729   for(int i=0;i<nbCells;i++)
2730     {
2731       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2732         ret->pushBackSilent(i);
2733     }
2734   return ret.retn();
2735 }
2736
2737 /*!
2738  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2739  */
2740 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2741 {
2742   const int *ptI=_nodal_connec_index->getConstPointer();
2743   const int *pt=_nodal_connec->getConstPointer();
2744   int nbOfCells=getNumberOfCells();
2745   int ret=0;
2746   for(int i=0;i<nbOfCells;i++)
2747     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2748       ret++;
2749   return ret;
2750 }
2751
2752 /*!
2753  * Returns the nodal connectivity of a given cell.
2754  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2755  * all returned node ids can be used in getCoordinatesOfNode().
2756  *  \param [in] cellId - an id of the cell of interest.
2757  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2758  *         cleared before the appending.
2759  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2760  */
2761 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2762 {
2763   const int *ptI=_nodal_connec_index->getConstPointer();
2764   const int *pt=_nodal_connec->getConstPointer();
2765   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2766     if(*w>=0)
2767       conn.push_back(*w);
2768 }
2769
2770 std::string MEDCouplingUMesh::simpleRepr() const
2771 {
2772   static const char msg0[]="No coordinates specified !";
2773   std::ostringstream ret;
2774   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2775   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2776   int tmpp1,tmpp2;
2777   double tt=getTime(tmpp1,tmpp2);
2778   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2779   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2780   if(_mesh_dim>=-1)
2781     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2782   else
2783     { ret << " Mesh dimension has not been set or is invalid !"; }
2784   if(_coords!=0)
2785     {
2786       const int spaceDim=getSpaceDimension();
2787       ret << spaceDim << "\nInfo attached on space dimension : ";
2788       for(int i=0;i<spaceDim;i++)
2789         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2790       ret << "\n";
2791     }
2792   else
2793     ret << msg0 << "\n";
2794   ret << "Number of nodes : ";
2795   if(_coords!=0)
2796     ret << getNumberOfNodes() << "\n";
2797   else
2798     ret << msg0 << "\n";
2799   ret << "Number of cells : ";
2800   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2801     ret << getNumberOfCells() << "\n";
2802   else
2803     ret << "No connectivity specified !" << "\n";
2804   ret << "Cell types present : ";
2805   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2806     {
2807       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2808       ret << cm.getRepr() << " ";
2809     }
2810   ret << "\n";
2811   return ret.str();
2812 }
2813
2814 std::string MEDCouplingUMesh::advancedRepr() const
2815 {
2816   std::ostringstream ret;
2817   ret << simpleRepr();
2818   ret << "\nCoordinates array : \n___________________\n\n";
2819   if(_coords)
2820     _coords->reprWithoutNameStream(ret);
2821   else
2822     ret << "No array set !\n";
2823   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2824   reprConnectivityOfThisLL(ret);
2825   return ret.str();
2826 }
2827
2828 /*!
2829  * This method returns a C++ code that is a dump of \a this.
2830  * This method will throw if this is not fully defined.
2831  */
2832 std::string MEDCouplingUMesh::cppRepr() const
2833 {
2834   static const char coordsName[]="coords";
2835   static const char connName[]="conn";
2836   static const char connIName[]="connI";
2837   checkFullyDefined();
2838   std::ostringstream ret; ret << "// coordinates" << std::endl;
2839   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2840   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2841   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2842   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2843   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2844   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2845   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2846   return ret.str();
2847 }
2848
2849 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2850 {
2851   std::ostringstream ret;
2852   reprConnectivityOfThisLL(ret);
2853   return ret.str();
2854 }
2855
2856 /*!
2857  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2858  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2859  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2860  * some algos).
2861  * 
2862  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2863  * 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
2864  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2865  */
2866 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2867 {
2868   int mdim=getMeshDimension();
2869   if(mdim<0)
2870     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2871   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2872   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2873   bool needToCpyCT=true;
2874   if(!_nodal_connec)
2875     {
2876       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2877       needToCpyCT=false;
2878     }
2879   else
2880     {
2881       tmp1=_nodal_connec;
2882       tmp1->incrRef();
2883     }
2884   if(!_nodal_connec_index)
2885     {
2886       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2887       needToCpyCT=false;
2888     }
2889   else
2890     {
2891       tmp2=_nodal_connec_index;
2892       tmp2->incrRef();
2893     }
2894   ret->setConnectivity(tmp1,tmp2,false);
2895   if(needToCpyCT)
2896     ret->_types=_types;
2897   if(!_coords)
2898     {
2899       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2900       ret->setCoords(coords);
2901     }
2902   else
2903     ret->setCoords(_coords);
2904   return ret.retn();
2905 }
2906
2907 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2908 {
2909   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2910     {
2911       int nbOfCells=getNumberOfCells();
2912       const int *c=_nodal_connec->getConstPointer();
2913       const int *ci=_nodal_connec_index->getConstPointer();
2914       for(int i=0;i<nbOfCells;i++)
2915         {
2916           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2917           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2918           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2919           stream << "\n";
2920         }
2921     }
2922   else
2923     stream << "Connectivity not defined !\n";
2924 }
2925
2926 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2927 {
2928   const int *ptI=_nodal_connec_index->getConstPointer();
2929   const int *pt=_nodal_connec->getConstPointer();
2930   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2931     return ptI[cellId+1]-ptI[cellId]-1;
2932   else
2933     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2934 }
2935
2936 /*!
2937  * Returns types of cells of the specified part of \a this mesh.
2938  * This method avoids computing sub-mesh explicitely to get its types.
2939  *  \param [in] begin - an array of cell ids of interest.
2940  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2941  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2942  *         describing the cell types. 
2943  *  \throw If the coordinates array is not set.
2944  *  \throw If the nodal connectivity of cells is not defined.
2945  *  \sa getAllGeoTypes()
2946  */
2947 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
2948 {
2949   checkFullyDefined();
2950   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2951   const int *conn=_nodal_connec->getConstPointer();
2952   const int *connIndex=_nodal_connec_index->getConstPointer();
2953   for(const int *w=begin;w!=end;w++)
2954     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2955   return ret;
2956 }
2957
2958 /*!
2959  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2960  * a set of types of cells constituting \a this mesh. 
2961  * This method is for advanced users having prepared their connectivity before. For
2962  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2963  *  \param [in] conn - the nodal connectivity array. 
2964  *  \param [in] connIndex - the nodal connectivity index array.
2965  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2966  *         mesh is updated.
2967  */
2968 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2969 {
2970   DataArrayInt::SetArrayIn(conn,_nodal_connec);
2971   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2972   if(isComputingTypes)
2973     computeTypes();
2974   declareAsNew();
2975 }
2976
2977 /*!
2978  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2979  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2980  */
2981 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2982                                                                                  _nodal_connec(0),_nodal_connec_index(0),
2983                                                                                 _types(other._types)
2984 {
2985   if(other._nodal_connec)
2986     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2987   if(other._nodal_connec_index)
2988     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2989 }
2990
2991 MEDCouplingUMesh::~MEDCouplingUMesh()
2992 {
2993   if(_nodal_connec)
2994     _nodal_connec->decrRef();
2995   if(_nodal_connec_index)
2996     _nodal_connec_index->decrRef();
2997 }
2998
2999 /*!
3000  * Recomputes a set of cell types of \a this mesh. For more info see
3001  * \ref MEDCouplingUMeshNodalConnectivity.
3002  */
3003 void MEDCouplingUMesh::computeTypes()
3004 {
3005   if(_nodal_connec && _nodal_connec_index)
3006     {
3007       _types.clear();
3008       const int *conn=_nodal_connec->getConstPointer();
3009       const int *connIndex=_nodal_connec_index->getConstPointer();
3010       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3011       if (nbOfElem > 0)
3012         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3013           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3014     }
3015 }
3016
3017 /*!
3018  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3019  */
3020 void MEDCouplingUMesh::checkFullyDefined() const
3021 {
3022   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3023     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3024 }
3025
3026 /*!
3027  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3028  */
3029 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3030 {
3031   if(!_nodal_connec_index || !_nodal_connec)
3032     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3033 }
3034
3035 /*!
3036  * Returns a number of cells constituting \a this mesh. 
3037  *  \return int - the number of cells in \a this mesh.
3038  *  \throw If the nodal connectivity of cells is not defined.
3039  */
3040 int MEDCouplingUMesh::getNumberOfCells() const
3041
3042   if(_nodal_connec_index)
3043     return _nodal_connec_index->getNumberOfTuples()-1;
3044   else
3045     if(_mesh_dim==-1)
3046       return 1;
3047     else
3048       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3049 }
3050
3051 /*!
3052  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3053  * mesh. For more info see \ref MEDCouplingMeshesPage.
3054  *  \return int - the dimension of \a this mesh.
3055  *  \throw If the mesh dimension is not defined using setMeshDimension().
3056  */
3057 int MEDCouplingUMesh::getMeshDimension() const
3058 {
3059   if(_mesh_dim<-1)
3060     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3061   return _mesh_dim;
3062 }
3063
3064 /*!
3065  * Returns a length of the nodal connectivity array.
3066  * This method is for test reason. Normally the integer returned is not useable by
3067  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3068  *  \return int - the length of the nodal connectivity array.
3069  */
3070 int MEDCouplingUMesh::getMeshLength() const
3071 {
3072   return _nodal_connec->getNbOfElems();
3073 }
3074
3075 /*!
3076  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3077  */
3078 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3079 {
3080   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3081   tinyInfo.push_back(getMeshDimension());
3082   tinyInfo.push_back(getNumberOfCells());
3083   if(_nodal_connec)
3084     tinyInfo.push_back(getMeshLength());
3085   else
3086     tinyInfo.push_back(-1);
3087 }
3088
3089 /*!
3090  * First step of unserialization process.
3091  */
3092 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3093 {
3094   return tinyInfo[6]<=0;
3095 }
3096
3097 /*!
3098  * Second step of serialization process.
3099  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3100  */
3101 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3102 {
3103   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3104   if(tinyInfo[5]!=-1)
3105     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3106 }
3107
3108 /*!
3109  * Third and final step of serialization process.
3110  */
3111 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3112 {
3113   MEDCouplingPointSet::serialize(a1,a2);
3114   if(getMeshDimension()>-1)
3115     {
3116       a1=DataArrayInt::New();
3117       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3118       int *ptA1=a1->getPointer();
3119       const int *conn=getNodalConnectivity()->getConstPointer();
3120       const int *index=getNodalConnectivityIndex()->getConstPointer();
3121       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3122       std::copy(conn,conn+getMeshLength(),ptA1);
3123     }
3124   else
3125     a1=0;
3126 }
3127
3128 /*!
3129  * Second and final unserialization process.
3130  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3131  */
3132 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3133 {
3134   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3135   setMeshDimension(tinyInfo[5]);
3136   if(tinyInfo[7]!=-1)
3137     {
3138       // Connectivity
3139       const int *recvBuffer=a1->getConstPointer();
3140       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3141       myConnecIndex->alloc(tinyInfo[6]+1,1);
3142       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3143       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3144       myConnec->alloc(tinyInfo[7],1);
3145       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3146       setConnectivity(myConnec, myConnecIndex);
3147     }
3148 }
3149
3150 /*!
3151  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3152  * CellIds are given using range specified by a start an end and step.
3153  */
3154 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3155 {
3156   checkFullyDefined();
3157   int ncell=getNumberOfCells();
3158   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3159   ret->_mesh_dim=_mesh_dim;
3160   ret->setCoords(_coords);
3161   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3162   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3163   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3164   int work=start;
3165   const int *conn=_nodal_connec->getConstPointer();
3166   const int *connIndex=_nodal_connec_index->getConstPointer();
3167   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3168     {
3169       if(work>=0 && work<ncell)
3170         {
3171           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3172         }
3173       else
3174         {
3175           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3176           throw INTERP_KERNEL::Exception(oss.str().c_str());
3177         }
3178     }
3179   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3180   int *newConnPtr=newConn->getPointer();
3181   std::set<INTERP_KERNEL::NormalizedCellType> types;
3182   work=start;
3183   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3184     {
3185       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3186       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3187     }
3188   ret->setConnectivity(newConn,newConnI,false);
3189   ret->_types=types;
3190   ret->copyTinyInfoFrom(this);
3191   return ret.retn();
3192 }
3193
3194 /*!
3195  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3196  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3197  * The return newly allocated mesh will share the same coordinates as \a this.
3198  */
3199 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3200 {
3201   checkConnectivityFullyDefined();
3202   int ncell=getNumberOfCells();
3203   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3204   ret->_mesh_dim=_mesh_dim;
3205   ret->setCoords(_coords);
3206   std::size_t nbOfElemsRet=std::distance(begin,end);
3207   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3208   connIndexRet[0]=0;
3209   const int *conn=_nodal_connec->getConstPointer();
3210   const int *connIndex=_nodal_connec_index->getConstPointer();
3211   int newNbring=0;
3212   for(const int *work=begin;work!=end;work++,newNbring++)
3213     {
3214       if(*work>=0 && *work<ncell)
3215         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3216       else
3217         {
3218           free(connIndexRet);
3219           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3220           throw INTERP_KERNEL::Exception(oss.str().c_str());
3221         }
3222     }
3223   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3224   int *connRetWork=connRet;
3225   std::set<INTERP_KERNEL::NormalizedCellType> types;
3226   for(const int *work=begin;work!=end;work++)
3227     {
3228       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3229       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3230     }
3231   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3232   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3233   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3234   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3235   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3236   ret->_types=types;
3237   ret->copyTinyInfoFrom(this);
3238   return ret.retn();
3239 }
3240
3241 /*!
3242  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3243  * mesh.<br>
3244  * For 1D cells, the returned field contains lengths.<br>
3245  * For 2D cells, the returned field contains areas.<br>
3246  * For 3D cells, the returned field contains volumes.
3247  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3248  *         orientation, i.e. the volume is always positive.
3249  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3250  *         and one time . The caller is to delete this field using decrRef() as it is no
3251  *         more needed.
3252  */
3253 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3254 {
3255   std::string name="MeasureOfMesh_";
3256   name+=getName();
3257   int nbelem=getNumberOfCells();
3258   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3259   field->setName(name);
3260   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3261   array->alloc(nbelem,1);
3262   double *area_vol=array->getPointer();
3263   field->setArray(array) ; array=0;
3264   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3265   field->synchronizeTimeWithMesh();
3266   if(getMeshDimension()!=-1)
3267     {
3268       int ipt;
3269       INTERP_KERNEL::NormalizedCellType type;
3270       int dim_space=getSpaceDimension();
3271       const double *coords=getCoords()->getConstPointer();
3272       const int *connec=getNodalConnectivity()->getConstPointer();
3273       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3274       for(int iel=0;iel<nbelem;iel++)
3275         {
3276           ipt=connec_index[iel];
3277           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3278           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);
3279         }
3280       if(isAbs)
3281         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3282     }
3283   else
3284     {
3285       area_vol[0]=std::numeric_limits<double>::max();
3286     }
3287   return field.retn();
3288 }
3289
3290 /*!
3291  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3292  * mesh.<br>
3293  * For 1D cells, the returned array contains lengths.<br>
3294  * For 2D cells, the returned array contains areas.<br>
3295  * For 3D cells, the returned array contains volumes.
3296  * This method avoids building explicitly a part of \a this mesh to perform the work.
3297  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3298  *         orientation, i.e. the volume is always positive.
3299  *  \param [in] begin - an array of cell ids of interest.
3300  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3301  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3302  *          delete this array using decrRef() as it is no more needed.
3303  * 
3304  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3305  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3306  *  \sa getMeasureField()
3307  */
3308 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3309 {
3310   std::string name="PartMeasureOfMesh_";
3311   name+=getName();
3312   int nbelem=(int)std::distance(begin,end);
3313   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3314   array->setName(name);
3315   array->alloc(nbelem,1);
3316   double *area_vol=array->getPointer();
3317   if(getMeshDimension()!=-1)
3318     {
3319       int ipt;
3320       INTERP_KERNEL::NormalizedCellType type;
3321       int dim_space=getSpaceDimension();
3322       const double *coords=getCoords()->getConstPointer();
3323       const int *connec=getNodalConnectivity()->getConstPointer();
3324       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3325       for(const int *iel=begin;iel!=end;iel++)
3326         {
3327           ipt=connec_index[*iel];
3328           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3329           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3330         }
3331       if(isAbs)
3332         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3333     }
3334   else
3335     {
3336       area_vol[0]=std::numeric_limits<double>::max();
3337     }
3338   return array.retn();
3339 }
3340
3341 /*!
3342  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3343  * \a this one. The returned field contains the dual cell volume for each corresponding
3344  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3345  *  the dual mesh in P1 sens of \a this.<br>
3346  * For 1D cells, the returned field contains lengths.<br>
3347  * For 2D cells, the returned field contains areas.<br>
3348  * For 3D cells, the returned field contains volumes.
3349  * This method is useful to check "P1*" conservative interpolators.
3350  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3351  *         orientation, i.e. the volume is always positive.
3352  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3353  *          nodes and one time. The caller is to delete this array using decrRef() as
3354  *          it is no more needed.
3355  */
3356 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3357 {
3358   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3359   std::string name="MeasureOnNodeOfMesh_";
3360   name+=getName();
3361   int nbNodes=getNumberOfNodes();
3362   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3363   double cst=1./((double)getMeshDimension()+1.);
3364   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3365   array->alloc(nbNodes,1);
3366   double *valsToFill=array->getPointer();
3367   std::fill(valsToFill,valsToFill+nbNodes,0.);
3368   const double *values=tmp->getArray()->getConstPointer();
3369   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3370   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3371   getReverseNodalConnectivity(da,daInd);
3372   const int *daPtr=da->getConstPointer();
3373   const int *daIPtr=daInd->getConstPointer();
3374   for(int i=0;i<nbNodes;i++)
3375     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3376       valsToFill[i]+=cst*values[*cell];
3377   ret->setMesh(this);
3378   ret->setArray(array);
3379   return ret.retn();
3380 }
3381
3382 /*!
3383  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3384  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3385  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3386  * and are normalized.
3387  * <br> \a this can be either 
3388  * - a  2D mesh in 2D or 3D space or 
3389  * - an 1D mesh in 2D space.
3390  * 
3391  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3392  *          cells and one time. The caller is to delete this field using decrRef() as
3393  *          it is no more needed.
3394  *  \throw If the nodal connectivity of cells is not defined.
3395  *  \throw If the coordinates array is not set.
3396  *  \throw If the mesh dimension is not set.
3397  *  \throw If the mesh and space dimension is not as specified above.
3398  */
3399 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3400 {
3401   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3402     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3403   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3404   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3405   int nbOfCells=getNumberOfCells();
3406   int nbComp=getMeshDimension()+1;
3407   array->alloc(nbOfCells,nbComp);
3408   double *vals=array->getPointer();
3409   const int *connI=_nodal_connec_index->getConstPointer();
3410   const int *conn=_nodal_connec->getConstPointer();
3411   const double *coords=_coords->getConstPointer();
3412   if(getMeshDimension()==2)
3413     {
3414       if(getSpaceDimension()==3)
3415         {
3416           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3417           const double *locPtr=loc->getConstPointer();
3418           for(int i=0;i<nbOfCells;i++,vals+=3)
3419             {
3420               int offset=connI[i];
3421               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3422               double n=INTERP_KERNEL::norm<3>(vals);
3423               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3424             }
3425         }
3426       else
3427         {
3428           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3429           const double *isAbsPtr=isAbs->getArray()->begin();
3430           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3431             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3432         }
3433     }
3434   else//meshdimension==1
3435     {
3436       double tmp[2];
3437       for(int i=0;i<nbOfCells;i++)
3438         {
3439           int offset=connI[i];
3440           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3441           double n=INTERP_KERNEL::norm<2>(tmp);
3442           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3443           *vals++=-tmp[1];
3444           *vals++=tmp[0];
3445         }
3446     }
3447   ret->setArray(array);
3448   ret->setMesh(this);
3449   ret->synchronizeTimeWithSupport();
3450   return ret.retn();
3451 }
3452
3453 /*!
3454  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3455  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3456  * and are normalized.
3457  * <br> \a this can be either 
3458  * - a  2D mesh in 2D or 3D space or 
3459  * - an 1D mesh in 2D space.
3460  * 
3461  * This method avoids building explicitly a part of \a this mesh to perform the work.
3462  *  \param [in] begin - an array of cell ids of interest.
3463  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3464  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3465  *          cells and one time. The caller is to delete this field using decrRef() as
3466  *          it is no more needed.
3467  *  \throw If the nodal connectivity of cells is not defined.
3468  *  \throw If the coordinates array is not set.
3469  *  \throw If the mesh dimension is not set.
3470  *  \throw If the mesh and space dimension is not as specified above.
3471  *  \sa buildOrthogonalField()
3472  *
3473  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3474  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3475  */
3476 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3477 {
3478   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3479     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3480   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3481   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3482   std::size_t nbelems=std::distance(begin,end);
3483   int nbComp=getMeshDimension()+1;
3484   array->alloc((int)nbelems,nbComp);
3485   double *vals=array->getPointer();
3486   const int *connI=_nodal_connec_index->getConstPointer();
3487   const int *conn=_nodal_connec->getConstPointer();
3488   const double *coords=_coords->getConstPointer();
3489   if(getMeshDimension()==2)
3490     {
3491       if(getSpaceDimension()==3)
3492         {
3493           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3494           const double *locPtr=loc->getConstPointer();
3495           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3496             {
3497               int offset=connI[*i];
3498               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3499               double n=INTERP_KERNEL::norm<3>(vals);
3500               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3501             }
3502         }
3503       else
3504         {
3505           for(std::size_t i=0;i<nbelems;i++)
3506             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3507         }
3508     }
3509   else//meshdimension==1
3510     {
3511       double tmp[2];
3512       for(const int *i=begin;i!=end;i++)
3513         {
3514           int offset=connI[*i];
3515           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3516           double n=INTERP_KERNEL::norm<2>(tmp);
3517           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3518           *vals++=-tmp[1];
3519           *vals++=tmp[0];
3520         }
3521     }
3522   ret->setArray(array);
3523   ret->setMesh(this);
3524   ret->synchronizeTimeWithSupport();
3525   return ret.retn();
3526 }
3527
3528 /*!
3529  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3530  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3531  * and are \b not normalized.
3532  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3533  *          cells and one time. The caller is to delete this field using decrRef() as
3534  *          it is no more needed.
3535  *  \throw If the nodal connectivity of cells is not defined.
3536  *  \throw If the coordinates array is not set.
3537  *  \throw If \a this->getMeshDimension() != 1.
3538  *  \throw If \a this mesh includes cells of type other than SEG2.
3539  */
3540 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3541 {
3542    if(getMeshDimension()!=1)
3543     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3544    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3545      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3546    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3547    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3548    int nbOfCells=getNumberOfCells();
3549    int spaceDim=getSpaceDimension();
3550    array->alloc(nbOfCells,spaceDim);
3551    double *pt=array->getPointer();
3552    const double *coo=getCoords()->getConstPointer();
3553    std::vector<int> conn;
3554    conn.reserve(2);
3555    for(int i=0;i<nbOfCells;i++)
3556      {
3557        conn.resize(0);
3558        getNodeIdsOfCell(i,conn);
3559        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3560      }
3561    ret->setArray(array);
3562    ret->setMesh(this);
3563    ret->synchronizeTimeWithSupport();
3564    return ret.retn();   
3565 }
3566
3567 /*!
3568  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3569  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3570  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3571  * from. If a result face is shared by two 3D cells, then the face in included twice in
3572  * the result mesh.
3573  *  \param [in] origin - 3 components of a point defining location of the plane.
3574  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3575  *         must be greater than 1e-6.
3576  *  \param [in] eps - half-thickness of the plane.
3577  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3578  *         producing correspondent 2D cells. The caller is to delete this array
3579  *         using decrRef() as it is no more needed.
3580  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3581  *         not share the node coordinates array with \a this mesh. The caller is to
3582  *         delete this mesh using decrRef() as it is no more needed.  
3583  *  \throw If the coordinates array is not set.
3584  *  \throw If the nodal connectivity of cells is not defined.
3585  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3586  *  \throw If magnitude of \a vec is less than 1e-6.
3587  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3588  *  \throw If \a this includes quadratic cells.
3589  */
3590 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3591 {
3592   checkFullyDefined();
3593   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3594     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3595   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3596   if(candidates->empty())
3597     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3598   std::vector<int> nodes;
3599   DataArrayInt *cellIds1D=0;
3600   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3601   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3602   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3603   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3604   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3605   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3606   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3607   revDesc2=0; revDescIndx2=0;
3608   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3609   revDesc1=0; revDescIndx1=0;
3610   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3611   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3612   //
3613   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3614   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3615     cut3DCurve[*it]=-1;
3616   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3617   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3618   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3619                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3620                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3621   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3622   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3623   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3624   if(cellIds2->empty())
3625     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3626   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3627   ret->setCoords(mDesc1->getCoords());
3628   ret->setConnectivity(conn,connI,true);
3629   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3630   return ret.retn();
3631 }
3632
3633 /*!
3634  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3635 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
3636 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3637 the result mesh.
3638  *  \param [in] origin - 3 components of a point defining location of the plane.
3639  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3640  *         must be greater than 1e-6.
3641  *  \param [in] eps - half-thickness of the plane.
3642  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3643  *         producing correspondent segments. The caller is to delete this array
3644  *         using decrRef() as it is no more needed.
3645  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3646  *         mesh in 3D space. This mesh does not share the node coordinates array with
3647  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3648  *         no more needed. 
3649  *  \throw If the coordinates array is not set.
3650  *  \throw If the nodal connectivity of cells is not defined.
3651  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3652  *  \throw If magnitude of \a vec is less than 1e-6.
3653  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3654  *  \throw If \a this includes quadratic cells.
3655  */
3656 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3657 {
3658   checkFullyDefined();
3659   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3660     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3661   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3662   if(candidates->empty())
3663     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3664   std::vector<int> nodes;
3665   DataArrayInt *cellIds1D=0;
3666   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3667   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3668   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3669   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3670   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3671   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3672   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3673   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3674   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3675   //
3676   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3677   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3678     cut3DCurve[*it]=-1;
3679   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3680   int ncellsSub=subMesh->getNumberOfCells();
3681   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3682   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3683                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3684                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3685   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3686   conn->alloc(0,1);
3687   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3688   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3689   for(int i=0;i<ncellsSub;i++)
3690     {
3691       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3692         {
3693           if(cut3DSurf[i].first!=-2)
3694             {
3695               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3696               connI->pushBackSilent(conn->getNumberOfTuples());
3697               cellIds2->pushBackSilent(i);
3698             }
3699           else
3700             {
3701               int cellId3DSurf=cut3DSurf[i].second;
3702               int offset=nodalI[cellId3DSurf]+1;
3703               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3704               for(int j=0;j<nbOfEdges;j++)
3705                 {
3706                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3707                   connI->pushBackSilent(conn->getNumberOfTuples());
3708                   cellIds2->pushBackSilent(cellId3DSurf);
3709                 }
3710             }
3711         }
3712     }
3713   if(cellIds2->empty())
3714     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3715   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3716   ret->setCoords(mDesc1->getCoords());
3717   ret->setConnectivity(conn,connI,true);
3718   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3719   return ret.retn();
3720 }
3721
3722 /*!
3723  * Finds cells whose bounding boxes intersect a given plane.
3724  *  \param [in] origin - 3 components of a point defining location of the plane.
3725  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3726  *         must be greater than 1e-6.
3727  *  \param [in] eps - half-thickness of the plane.
3728  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3729  *         cells. The caller is to delete this array using decrRef() as it is no more
3730  *         needed.
3731  *  \throw If the coordinates array is not set.
3732  *  \throw If the nodal connectivity of cells is not defined.
3733  *  \throw If \a this->getSpaceDimension() != 3.
3734  *  \throw If magnitude of \a vec is less than 1e-6.
3735  *  \sa buildSlice3D()
3736  */
3737 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3738 {
3739   checkFullyDefined();
3740   if(getSpaceDimension()!=3)
3741     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3742   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3743   if(normm<1e-6)
3744     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3745   double vec2[3];
3746   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3747   double angle=acos(vec[2]/normm);
3748   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3749   double bbox[6];
3750   if(angle>eps)
3751     {
3752       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3753       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3754       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3755       mw->setCoords(coo);
3756       mw->getBoundingBox(bbox);
3757       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3758       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3759     }
3760   else
3761     {
3762       getBoundingBox(bbox);
3763       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3764       cellIds=getCellsInBoundingBox(bbox,eps);
3765     }
3766   return cellIds.retn();
3767 }
3768
3769 /*!
3770  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3771  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3772  * No consideration of coordinate is done by this method.
3773  * 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)
3774  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3775  */
3776 bool MEDCouplingUMesh::isContiguous1D() const
3777 {
3778   if(getMeshDimension()!=1)
3779     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3780   int nbCells=getNumberOfCells();
3781   if(nbCells<1)
3782     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3783   const int *connI=_nodal_connec_index->getConstPointer();
3784   const int *conn=_nodal_connec->getConstPointer();
3785   int ref=conn[connI[0]+2];
3786   for(int i=1;i<nbCells;i++)
3787     {
3788       if(conn[connI[i]+1]!=ref)
3789         return false;
3790       ref=conn[connI[i]+2];
3791     }
3792   return true;
3793 }
3794
3795 /*!
3796  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3797  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3798  * \param pt reference point of the line
3799  * \param v normalized director vector of the line
3800  * \param eps max precision before throwing an exception
3801  * \param res output of size this->getNumberOfCells
3802  */
3803 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3804 {
3805   if(getMeshDimension()!=1)
3806     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3807    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3808      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3809    if(getSpaceDimension()!=3)
3810      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3811    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3812    const double *fPtr=f->getArray()->getConstPointer();
3813    double tmp[3];
3814    for(int i=0;i<getNumberOfCells();i++)
3815      {
3816        const double *tmp1=fPtr+3*i;
3817        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3818        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3819        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3820        double n1=INTERP_KERNEL::norm<3>(tmp);
3821        n1/=INTERP_KERNEL::norm<3>(tmp1);
3822        if(n1>eps)
3823          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3824      }
3825    const double *coo=getCoords()->getConstPointer();
3826    for(int i=0;i<getNumberOfNodes();i++)
3827      {
3828        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3829        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3830        res[i]=std::accumulate(tmp,tmp+3,0.);
3831      }
3832 }
3833
3834 /*!
3835  * 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. 
3836  * \a this is expected to be a mesh so that its space dimension is equal to its
3837  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3838  * 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).
3839  
3840  * 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
3841  * 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).
3842  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3843  *
3844  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3845  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3846  *
3847  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3848  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3849  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3850  * \return the positive value of the distance.
3851  * \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
3852  * dimension - 1.
3853  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3854  */
3855 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3856 {
3857   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3858   if(meshDim!=spaceDim-1)
3859     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3860   if(meshDim!=2 && meshDim!=1)
3861     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3862   checkFullyDefined();
3863   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3864     { 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()); }
3865   DataArrayInt *ret1=0;
3866   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3867   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3868   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3869   cellId=*ret1Safe->begin();
3870   return *ret0->begin();
3871 }
3872
3873 /*!
3874  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3875  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3876  * 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
3877  * 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).
3878  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3879  * 
3880  * \a this is expected to be a mesh so that its space dimension is equal to its
3881  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3882  * 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).
3883  *
3884  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3885  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3886  *
3887  * \param [in] pts the list of points in which each tuple represents a point
3888  * \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.
3889  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3890  * \throw if number of components of \a pts is not equal to the space dimension.
3891  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3892  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3893  */
3894 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3895 {
3896   if(!pts)
3897     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3898   pts->checkAllocated();
3899   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3900   if(meshDim!=spaceDim-1)
3901     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3902   if(meshDim!=2 && meshDim!=1)
3903     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3904   if(pts->getNumberOfComponents()!=spaceDim)
3905     {
3906       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3907       throw INTERP_KERNEL::Exception(oss.str().c_str());
3908     }
3909   checkFullyDefined();
3910   int nbCells=getNumberOfCells();
3911   if(nbCells==0)
3912     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3913   int nbOfPts=pts->getNumberOfTuples();
3914   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3915   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3916   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3917   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3918   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3919   const double *bbox(bboxArr->begin());
3920   switch(spaceDim)
3921     {
3922     case 3:
3923       {
3924         BBTreeDst<3> myTree(bbox,0,0,nbCells);
3925         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3926           {
3927             double x=std::numeric_limits<double>::max();
3928             std::vector<int> elems;
3929             myTree.getMinDistanceOfMax(ptsPtr,x);
3930             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3931             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3932           }
3933         break;
3934       }
3935     case 2:
3936       {
3937         BBTreeDst<2> myTree(bbox,0,0,nbCells);
3938         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3939           {
3940             double x=std::numeric_limits<double>::max();
3941             std::vector<int> elems;
3942             myTree.getMinDistanceOfMax(ptsPtr,x);
3943             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3944             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3945           }
3946         break;
3947       }
3948     default:
3949       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3950     }
3951   cellIds=ret1.retn();
3952   return ret0.retn();
3953 }
3954
3955 /*!
3956  * \param [in] pt the start pointer (included) of the coordinates of the point
3957  * \param [in] cellIdsBg the start pointer (included) of cellIds
3958  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3959  * \param [in] nc nodal connectivity
3960  * \param [in] ncI nodal connectivity index
3961  * \param [in,out] ret0 the min distance between \a this and the external input point
3962  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3963  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3964  */
3965 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)
3966 {
3967   cellId=-1;
3968   ret0=std::numeric_limits<double>::max();
3969   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3970     {
3971       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3972         {
3973         case INTERP_KERNEL::NORM_TRI3:
3974           {
3975             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3976             if(tmp<ret0)
3977               { ret0=tmp; cellId=*zeCell; }
3978             break;
3979           }
3980         case INTERP_KERNEL::NORM_QUAD4:
3981         case INTERP_KERNEL::NORM_POLYGON:
3982           {
3983             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3984             if(tmp<ret0)
3985               { ret0=tmp; cellId=*zeCell; }
3986             break;
3987           }
3988         default:
3989           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3990         }
3991     }
3992 }
3993
3994 /*!
3995  * \param [in] pt the start pointer (included) of the coordinates of the point
3996  * \param [in] cellIdsBg the start pointer (included) of cellIds
3997  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3998  * \param [in] nc nodal connectivity
3999  * \param [in] ncI nodal connectivity index
4000  * \param [in,out] ret0 the min distance between \a this and the external input point
4001  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4002  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4003  */
4004 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)
4005 {
4006   cellId=-1;
4007   ret0=std::numeric_limits<double>::max();
4008   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4009     {
4010        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4011         {
4012         case INTERP_KERNEL::NORM_SEG2:
4013           {
4014             std::size_t uselessEntry=0;
4015             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4016             tmp=sqrt(tmp);
4017             if(tmp<ret0)
4018               { ret0=tmp; cellId=*zeCell; }
4019             break;
4020           }
4021         default:
4022           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4023         }
4024     }
4025 }
4026
4027 /*!
4028  * Finds cells in contact with a ball (i.e. a point with precision). 
4029  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4030  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4031  *
4032  * \warning This method is suitable if the caller intends to evaluate only one
4033  *          point, for more points getCellsContainingPoints() is recommended as it is
4034  *          faster. 
4035  *  \param [in] pos - array of coordinates of the ball central point.
4036  *  \param [in] eps - ball radius.
4037  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4038  *         if there are no such cells.
4039  *  \throw If the coordinates array is not set.
4040  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4041  */
4042 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4043 {
4044   std::vector<int> elts;
4045   getCellsContainingPoint(pos,eps,elts);
4046   if(elts.empty())
4047     return -1;
4048   return elts.front();
4049 }
4050
4051 /*!
4052  * Finds cells in contact with a ball (i.e. a point with precision).
4053  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4054  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4055  * \warning This method is suitable if the caller intends to evaluate only one
4056  *          point, for more points getCellsContainingPoints() is recommended as it is
4057  *          faster. 
4058  *  \param [in] pos - array of coordinates of the ball central point.
4059  *  \param [in] eps - ball radius.
4060  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4061  *         before inserting ids.
4062  *  \throw If the coordinates array is not set.
4063  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4064  *
4065  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4066  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4067  */
4068 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4069 {
4070   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4071   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4072   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4073 }
4074
4075 /// @cond INTERNAL
4076
4077 namespace ParaMEDMEM
4078 {
4079   template<const int SPACEDIMM>
4080   class DummyClsMCUG
4081   {
4082   public:
4083     static const int MY_SPACEDIM=SPACEDIMM;
4084     static const int MY_MESHDIM=8;
4085     typedef int MyConnType;
4086     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4087     // begin
4088     // useless, but for windows compilation ...
4089     const double* getCoordinatesPtr() const { return 0; }
4090     const int* getConnectivityPtr() const { return 0; }
4091     const int* getConnectivityIndexPtr() const { return 0; }
4092     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4093     // end
4094   };
4095
4096   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4097   {
4098     INTERP_KERNEL::Edge *ret=0;
4099     switch(typ)
4100       {
4101       case INTERP_KERNEL::NORM_SEG2:
4102         {
4103           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4104           break;
4105         }
4106       case INTERP_KERNEL::NORM_SEG3:
4107         {
4108           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4109           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4110           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4111           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4112           bool colinearity=inters.areColinears();
4113           delete e1; delete e2;
4114           if(colinearity)
4115             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4116           else
4117             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4118           mapp2[bg[2]].second=false;
4119           break;
4120         }
4121       default:
4122         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4123       }
4124     return ret;
4125   }
4126
4127   /*!
4128    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4129    * the global mesh 'mDesc'.
4130    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4131    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4132    */
4133   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4134       std::map<INTERP_KERNEL::Node *,int>& mapp)
4135       throw(INTERP_KERNEL::Exception)
4136   {
4137     mapp.clear();
4138     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.
4139     const double *coo=mDesc->getCoords()->getConstPointer();
4140     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4141     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4142     std::set<int> s;
4143     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4144       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4145     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4146       {
4147         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4148         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4149       }
4150     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4151     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4152       {
4153         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4154         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4155       }
4156     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4157       {
4158         if((*it2).second.second)
4159           mapp[(*it2).second.first]=(*it2).first;
4160         ((*it2).second.first)->decrRef();
4161       }
4162     return ret;
4163   }
4164
4165   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4166   {
4167     if(nodeId>=offset2)
4168       {
4169         int locId=nodeId-offset2;
4170         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4171       }
4172     if(nodeId>=offset1)
4173       {
4174         int locId=nodeId-offset1;
4175         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4176       }
4177     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4178   }
4179
4180   /**
4181    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4182    */
4183   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4184                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4185                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4186   {
4187     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4188       {
4189         int eltId1=abs(*desc1)-1;
4190         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4191           {
4192             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4193             if(it==mappRev.end())
4194               {
4195                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4196                 mapp[node]=*it1;
4197                 mappRev[*it1]=node;
4198               }
4199           }
4200       }
4201   }
4202 }
4203
4204 /// @endcond
4205
4206 template<int SPACEDIM>
4207 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4208                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4209 {
4210   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4211   int *eltsIndexPtr(eltsIndex->getPointer());
4212   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4213   const double *bbox(bboxArr->begin());
4214   int nbOfCells=getNumberOfCells();
4215   const int *conn=_nodal_connec->getConstPointer();
4216   const int *connI=_nodal_connec_index->getConstPointer();
4217   double bb[2*SPACEDIM];
4218   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4219   for(int i=0;i<nbOfPoints;i++)
4220     {
4221       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4222       for(int j=0;j<SPACEDIM;j++)
4223         {
4224           bb[2*j]=pos[SPACEDIM*i+j];
4225           bb[2*j+1]=pos[SPACEDIM*i+j];
4226         }
4227       std::vector<int> candidates;
4228       myTree.getIntersectingElems(bb,candidates);
4229       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4230         {
4231           int sz(connI[(*iter)+1]-connI[*iter]-1);
4232           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4233           bool status(false);
4234           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4235             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4236           else
4237             {
4238               if(SPACEDIM!=2)
4239                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4240               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4241               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4242               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4243               INTERP_KERNEL::QuadraticPolygon *pol(0);
4244               for(int j=0;j<sz;j++)
4245                 {
4246                   int nodeId(conn[connI[*iter]+1+j]);
4247                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4248                 }
4249               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4250                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4251               else
4252                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4253               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4254               double a(0.),b(0.),c(0.);
4255               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4256               status=pol->isInOrOut2(n);
4257               delete pol; n->decrRef();
4258             }
4259           if(status)
4260             {
4261               eltsIndexPtr[i+1]++;
4262               elts->pushBackSilent(*iter);
4263             }
4264         }
4265     }
4266 }
4267 /*!
4268  * Finds cells in contact with several balls (i.e. points with precision).
4269  * This method is an extension of getCellContainingPoint() and
4270  * getCellsContainingPoint() for the case of multiple points.
4271  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4272  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4273  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4274  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4275  *         this->getSpaceDimension() * \a nbOfPoints 
4276  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4277  *  \param [in] eps - radius of balls (i.e. the precision).
4278  *  \param [out] elts - vector returning ids of found cells.
4279  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4280  *         dividing cell ids in \a elts into groups each referring to one
4281  *         point. Its every element (except the last one) is an index pointing to the
4282  *         first id of a group of cells. For example cells in contact with the *i*-th
4283  *         point are described by following range of indices:
4284  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4285  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4286  *         Number of cells in contact with the *i*-th point is
4287  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4288  *  \throw If the coordinates array is not set.
4289  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4290  *
4291  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4292  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4293  */
4294 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4295                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4296 {
4297   int spaceDim=getSpaceDimension();
4298   int mDim=getMeshDimension();
4299   if(spaceDim==3)
4300     {
4301       if(mDim==3)
4302         {
4303           const double *coords=_coords->getConstPointer();
4304           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4305         }
4306       /*else if(mDim==2)
4307         {
4308           
4309         }*/
4310       else
4311         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4312     }
4313   else if(spaceDim==2)
4314     {
4315       if(mDim==2)
4316         {
4317           const double *coords=_coords->getConstPointer();
4318           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4319         }
4320       else
4321         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4322     }
4323   else if(spaceDim==1)
4324     {
4325       if(mDim==1)
4326         {
4327           const double *coords=_coords->getConstPointer();
4328           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4329         }
4330       else
4331         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4332     }
4333   else
4334     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4335 }
4336
4337 /*!
4338  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4339  * least two its edges intersect each other anywhere except their extremities. An
4340  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4341  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4342  *         cleared before filling in.
4343  *  \param [in] eps - precision.
4344  *  \throw If \a this->getMeshDimension() != 2.
4345  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4346  */
4347 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4348 {
4349   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4350   if(getMeshDimension()!=2)
4351     throw INTERP_KERNEL::Exception(msg);
4352   int spaceDim=getSpaceDimension();
4353   if(spaceDim!=2 && spaceDim!=3)
4354     throw INTERP_KERNEL::Exception(msg);
4355   const int *conn=_nodal_connec->getConstPointer();
4356   const int *connI=_nodal_connec_index->getConstPointer();
4357   int nbOfCells=getNumberOfCells();
4358   std::vector<double> cell2DinS2;
4359   for(int i=0;i<nbOfCells;i++)
4360     {
4361       int offset=connI[i];
4362       int nbOfNodesForCell=connI[i+1]-offset-1;
4363       if(nbOfNodesForCell<=3)
4364         continue;
4365       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4366       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4367       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4368         cells.push_back(i);
4369       cell2DinS2.clear();
4370     }
4371 }
4372
4373 /*!
4374  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4375  *
4376  * 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.
4377  * 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.
4378  * 
4379  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4380  * This convex envelop is computed using Jarvis march algorithm.
4381  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4382  * 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)
4383  * 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.
4384  *
4385  * \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.
4386  */
4387 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4388 {
4389   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4390     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4391   checkFullyDefined();
4392   const double *coords=getCoords()->getConstPointer();
4393   int nbOfCells=getNumberOfCells();
4394   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4395   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4397   int *workIndexOut=nodalConnecIndexOut->getPointer();
4398   *workIndexOut=0;
4399   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4400   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4401   std::set<INTERP_KERNEL::NormalizedCellType> types;
4402   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4403   isChanged->alloc(0,1);
4404   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4405     {
4406       int pos=nodalConnecOut->getNumberOfTuples();
4407       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4408         isChanged->pushBackSilent(i);
4409       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4410       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4411     }
4412   if(isChanged->empty())
4413     return 0;
4414   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4415   _types=types;
4416   return isChanged.retn();
4417 }
4418
4419 /*!
4420  * This method is \b NOT const because it can modify \a this.
4421  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4422  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4423  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4424  * \b 1 for translation and rotation around point of 'mesh1D'.
4425  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4426  */
4427 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4428 {
4429   checkFullyDefined();
4430   mesh1D->checkFullyDefined();
4431   if(!mesh1D->isContiguous1D())
4432     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4433   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4434     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4435   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4436     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4437   if(mesh1D->getMeshDimension()!=1)
4438     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4439   bool isQuad=false;
4440   if(isPresenceOfQuadratic())
4441     {
4442       if(mesh1D->isFullyQuadratic())
4443         isQuad=true;
4444       else
4445         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4446     }
4447   zipCoords();
4448   int oldNbOfNodes=getNumberOfNodes();
4449   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4450   switch(policy)
4451     {
4452     case 0:
4453       {
4454         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4455         break;
4456       }
4457     case 1:
4458       {
4459         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4460         break;
4461       }
4462     default:
4463       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4464     }
4465   setCoords(newCoords);
4466   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4467   updateTime();
4468   return ret.retn();
4469 }
4470
4471 /*!
4472  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4473  * If it is not the case an exception will be thrown.
4474  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4475  * intersection of plane defined by ('origin','vec').
4476  * This method has one in/out parameter : 'cut3DCurve'.
4477  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4478  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4479  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4480  * This method will throw an exception if \a this contains a non linear segment.
4481  */
4482 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4483 {
4484   checkFullyDefined();
4485   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4486     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4487   int ncells=getNumberOfCells();
4488   int nnodes=getNumberOfNodes();
4489   double vec2[3],vec3[3],vec4[3];
4490   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4491   if(normm<1e-6)
4492     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4493   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4494   const int *conn=_nodal_connec->getConstPointer();
4495   const int *connI=_nodal_connec_index->getConstPointer();
4496   const double *coo=_coords->getConstPointer();
4497   std::vector<double> addCoo;
4498   for(int i=0;i<ncells;i++)
4499     {
4500       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4501         {
4502           if(cut3DCurve[i]==-2)
4503             {
4504               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4505               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];
4506               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4507               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4508               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4509                 {
4510                   const double *st2=coo+3*st;
4511                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4512                   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]));
4513                   if(pos>eps && pos<1-eps)
4514                     {
4515                       int nNode=((int)addCoo.size())/3;
4516                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4517                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4518                       cut3DCurve[i]=nnodes+nNode;
4519                     }
4520                 }
4521             }
4522         }
4523       else
4524         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4525     }
4526   if(!addCoo.empty())
4527     {
4528       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4529       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4530       coo2->alloc(newNbOfNodes,3);
4531       double *tmp=coo2->getPointer();
4532       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4533       std::copy(addCoo.begin(),addCoo.end(),tmp);
4534       DataArrayDouble::SetArrayIn(coo2,_coords);
4535     }
4536 }
4537
4538 /*!
4539  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4540  * \param mesh1D is the input 1D mesh used for translation computation.
4541  * \return newCoords new coords filled by this method. 
4542  */
4543 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4544 {
4545   int oldNbOfNodes=getNumberOfNodes();
4546   int nbOf1DCells=mesh1D->getNumberOfCells();
4547   int spaceDim=getSpaceDimension();
4548   DataArrayDouble *ret=DataArrayDouble::New();
4549   std::vector<bool> isQuads;
4550   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4551   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4552   double *retPtr=ret->getPointer();
4553   const double *coords=getCoords()->getConstPointer();
4554   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4555   std::vector<int> v;
4556   std::vector<double> c;
4557   double vec[3];
4558   v.reserve(3);
4559   c.reserve(6);
4560   for(int i=0;i<nbOf1DCells;i++)
4561     {
4562       v.resize(0);
4563       mesh1D->getNodeIdsOfCell(i,v);
4564       c.resize(0);
4565       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4566       mesh1D->getCoordinatesOfNode(v[0],c);
4567       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4568       for(int j=0;j<oldNbOfNodes;j++)
4569         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4570       if(isQuad)
4571         {
4572           c.resize(0);
4573           mesh1D->getCoordinatesOfNode(v[1],c);
4574           mesh1D->getCoordinatesOfNode(v[0],c);
4575           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4576           for(int j=0;j<oldNbOfNodes;j++)
4577             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4578         }
4579     }
4580   ret->copyStringInfoFrom(*getCoords());
4581   return ret;
4582 }
4583
4584 /*!
4585  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4586  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4587  * \return newCoords new coords filled by this method. 
4588  */
4589 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4590 {
4591   if(mesh1D->getSpaceDimension()==2)
4592     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4593   if(mesh1D->getSpaceDimension()==3)
4594     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4595   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4596 }
4597
4598 /*!
4599  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4600  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4601  * \return newCoords new coords filled by this method. 
4602  */
4603 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4604 {
4605   if(isQuad)
4606     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4607   int oldNbOfNodes=getNumberOfNodes();
4608   int nbOf1DCells=mesh1D->getNumberOfCells();
4609   if(nbOf1DCells<2)
4610     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4611   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4612   int nbOfLevsInVec=nbOf1DCells+1;
4613   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4614   double *retPtr=ret->getPointer();
4615   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4616   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4617   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4618   tmp->setCoords(tmp2);
4619   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4620   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4621   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4622   for(int i=1;i<nbOfLevsInVec;i++)
4623     {
4624       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4625       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4626       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4627       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4628       tmp->translate(vec);
4629       double tmp3[2],radius,alpha,alpha0;
4630       const double *p0=i+1<nbOfLevsInVec?begin:third;
4631       const double *p1=i+1<nbOfLevsInVec?end:begin;
4632       const double *p2=i+1<nbOfLevsInVec?third:end;
4633       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4634       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]);
4635       double angle=acos(cosangle/(radius*radius));
4636       tmp->rotate(end,0,angle);
4637       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4638     }
4639   return ret.retn();
4640 }
4641
4642 /*!
4643  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4644  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4645  * \return newCoords new coords filled by this method. 
4646  */
4647 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4648 {
4649   if(isQuad)
4650     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4651   int oldNbOfNodes=getNumberOfNodes();
4652   int nbOf1DCells=mesh1D->getNumberOfCells();
4653   if(nbOf1DCells<2)
4654     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4655   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4656   int nbOfLevsInVec=nbOf1DCells+1;
4657   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4658   double *retPtr=ret->getPointer();
4659   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4660   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4661   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4662   tmp->setCoords(tmp2);
4663   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4664   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4665   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4666   for(int i=1;i<nbOfLevsInVec;i++)
4667     {
4668       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4669       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4670       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4671       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4672       tmp->translate(vec);
4673       double tmp3[2],radius,alpha,alpha0;
4674       const double *p0=i+1<nbOfLevsInVec?begin:third;
4675       const double *p1=i+1<nbOfLevsInVec?end:begin;
4676       const double *p2=i+1<nbOfLevsInVec?third:end;
4677       double vecPlane[3]={
4678         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4679         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4680         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4681       };
4682       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4683       if(norm>1.e-7)
4684         {
4685           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4686           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4687           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4688           double s2=norm2;
4689           double c2=cos(asin(s2));
4690           double m[3][3]={
4691             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4692             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4693             {-vec2[1]*s2, vec2[0]*s2, c2}
4694           };
4695           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]};
4696           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]};
4697           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]};
4698           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4699           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]);
4700           double angle=acos(cosangle/(radius*radius));
4701           tmp->rotate(end,vecPlane,angle);
4702           
4703         }
4704       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4705     }
4706   return ret.retn();
4707 }
4708
4709 /*!
4710  * This method is private because not easy to use for end user. This method is const contrary to
4711  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4712  * the coords sorted slice by slice.
4713  * \param isQuad specifies presence of quadratic cells.
4714  */
4715 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4716 {
4717   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4718   int nbOf2DCells=getNumberOfCells();
4719   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4720   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4721   const int *conn=_nodal_connec->getConstPointer();
4722   const int *connI=_nodal_connec_index->getConstPointer();
4723   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4724   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4725   newConnI->alloc(nbOf3DCells+1,1);
4726   int *newConnIPtr=newConnI->getPointer();
4727   *newConnIPtr++=0;
4728   std::vector<int> newc;
4729   for(int j=0;j<nbOf2DCells;j++)
4730     {
4731       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4732       *newConnIPtr++=(int)newc.size();
4733     }
4734   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4735   int *newConnPtr=newConn->getPointer();
4736   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4737   newConnIPtr=newConnI->getPointer();
4738   for(int iz=0;iz<nbOf1DCells;iz++)
4739     {
4740       if(iz!=0)
4741         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4742       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4743         {
4744           int icell=(int)(iter-newc.begin());
4745           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4746             {
4747               if(*iter!=-1)
4748                 *newConnPtr=(*iter)+iz*deltaPerLev;
4749               else
4750                 *newConnPtr=-1;
4751             }
4752           else
4753             *newConnPtr=(*iter);
4754         }
4755     }
4756   ret->setConnectivity(newConn,newConnI,true);
4757   ret->setCoords(getCoords());
4758   return ret;
4759 }
4760
4761 /*!
4762  * Checks if \a this mesh is constituted by only quadratic cells.
4763  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4764  *  \throw If the coordinates array is not set.
4765  *  \throw If the nodal connectivity of cells is not defined.
4766  */
4767 bool MEDCouplingUMesh::isFullyQuadratic() const
4768 {
4769   checkFullyDefined();
4770   bool ret=true;
4771   int nbOfCells=getNumberOfCells();
4772   for(int i=0;i<nbOfCells && ret;i++)
4773     {
4774       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4775       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4776       ret=cm.isQuadratic();
4777     }
4778   return ret;
4779 }
4780
4781 /*!
4782  * Checks if \a this mesh includes any quadratic cell.
4783  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4784  *  \throw If the coordinates array is not set.
4785  *  \throw If the nodal connectivity of cells is not defined.
4786  */
4787 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4788 {
4789   checkFullyDefined();
4790   bool ret=false;
4791   int nbOfCells=getNumberOfCells();
4792   for(int i=0;i<nbOfCells && !ret;i++)
4793     {
4794       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4795       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4796       ret=cm.isQuadratic();
4797     }
4798   return ret;
4799 }
4800
4801 /*!
4802  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4803  * this mesh, it remains unchanged.
4804  *  \throw If the coordinates array is not set.
4805  *  \throw If the nodal connectivity of cells is not defined.
4806  */
4807 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4808 {
4809   checkFullyDefined();
4810   int nbOfCells=getNumberOfCells();
4811   int delta=0;
4812   const int *iciptr=_nodal_connec_index->getConstPointer();
4813   for(int i=0;i<nbOfCells;i++)
4814     {
4815       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4816       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4817       if(cm.isQuadratic())
4818         {
4819           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4820           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4821           if(!cml.isDynamic())
4822             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4823           else
4824             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4825         }
4826     }
4827   if(delta==0)
4828     return ;
4829   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4831   const int *icptr=_nodal_connec->getConstPointer();
4832   newConn->alloc(getMeshLength()-delta,1);
4833   newConnI->alloc(nbOfCells+1,1);
4834   int *ocptr=newConn->getPointer();
4835   int *ociptr=newConnI->getPointer();
4836   *ociptr=0;
4837   _types.clear();
4838   for(int i=0;i<nbOfCells;i++,ociptr++)
4839     {
4840       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4841       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4842       if(!cm.isQuadratic())
4843         {
4844           _types.insert(type);
4845           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4846           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4847         }
4848       else
4849         {
4850           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4851           _types.insert(typel);
4852           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4853           int newNbOfNodes=cml.getNumberOfNodes();
4854           if(cml.isDynamic())
4855             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4856           *ocptr++=(int)typel;
4857           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4858           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4859         }
4860     }
4861   setConnectivity(newConn,newConnI,false);
4862 }
4863
4864 /*!
4865  * This method converts all linear cell in \a this to quadratic one.
4866  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4867  * 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)
4868  * 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.
4869  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4870  * end of the existing coordinates.
4871  * 
4872  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4873  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4874  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4875  * 
4876  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4877  *
4878  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4879  */
4880 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4881 {
4882   DataArrayInt *conn=0,*connI=0;
4883   DataArrayDouble *coords=0;
4884   std::set<INTERP_KERNEL::NormalizedCellType> types;
4885   checkFullyDefined();
4886   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4887   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4888   int meshDim=getMeshDimension();
4889   switch(conversionType)
4890     {
4891     case 0:
4892       switch(meshDim)
4893         {
4894         case 1:
4895           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4896           connSafe=conn; connISafe=connI; coordsSafe=coords;
4897           break;
4898         case 2:
4899           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4900           connSafe=conn; connISafe=connI; coordsSafe=coords;
4901           break;
4902         case 3:
4903           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4904           connSafe=conn; connISafe=connI; coordsSafe=coords;
4905           break;
4906         default:
4907           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4908         }
4909       break;
4910     case 1:
4911       {
4912         switch(meshDim)
4913         {
4914         case 1:
4915           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4916           connSafe=conn; connISafe=connI; coordsSafe=coords;
4917           break;
4918         case 2:
4919           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4920           connSafe=conn; connISafe=connI; coordsSafe=coords;
4921           break;
4922         case 3:
4923           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4924           connSafe=conn; connISafe=connI; coordsSafe=coords;
4925           break;
4926         default:
4927           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4928         }
4929         break;
4930       }
4931     default:
4932       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4933     }
4934   setConnectivity(connSafe,connISafe,false);
4935   _types=types;
4936   setCoords(coordsSafe);
4937   return ret.retn();
4938 }
4939
4940 /*!
4941  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4942  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4943  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4944  */
4945 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
4946 {
4947   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4948   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4949   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4950   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4951   int nbOfCells=getNumberOfCells();
4952   int nbOfNodes=getNumberOfNodes();
4953   const int *cPtr=_nodal_connec->getConstPointer();
4954   const int *icPtr=_nodal_connec_index->getConstPointer();
4955   int lastVal=0,offset=nbOfNodes;
4956   for(int i=0;i<nbOfCells;i++,icPtr++)
4957     {
4958       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4959       if(type==INTERP_KERNEL::NORM_SEG2)
4960         {
4961           types.insert(INTERP_KERNEL::NORM_SEG3);
4962           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4963           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4964           newConn->pushBackSilent(offset++);
4965           lastVal+=4;
4966           newConnI->pushBackSilent(lastVal);
4967           ret->pushBackSilent(i);
4968         }
4969       else
4970         {
4971           types.insert(type);
4972           lastVal+=(icPtr[1]-icPtr[0]);
4973           newConnI->pushBackSilent(lastVal);
4974           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4975         }
4976     }
4977   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4978   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4979   return ret.retn();
4980 }
4981
4982 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
4983 {
4984   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4985   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4986   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4987   //
4988   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4989   DataArrayInt *conn1D=0,*conn1DI=0;
4990   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4991   DataArrayDouble *coordsTmp=0;
4992   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4993   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4994   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4995   const int *c1DPtr=conn1D->begin();
4996   const int *c1DIPtr=conn1DI->begin();
4997   int nbOfCells=getNumberOfCells();
4998   const int *cPtr=_nodal_connec->getConstPointer();
4999   const int *icPtr=_nodal_connec_index->getConstPointer();
5000   int lastVal=0;
5001   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5002     {
5003       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5004       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5005       if(!cm.isQuadratic())
5006         {
5007           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5008           types.insert(typ2); newConn->pushBackSilent(typ2);
5009           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5010           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5011             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5012           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5013           newConnI->pushBackSilent(lastVal);
5014           ret->pushBackSilent(i);
5015         }
5016       else
5017         {
5018           types.insert(typ);
5019           lastVal+=(icPtr[1]-icPtr[0]);
5020           newConnI->pushBackSilent(lastVal);
5021           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5022         }
5023     }
5024   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5025   return ret.retn();
5026 }
5027
5028 /*!
5029  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5030  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5031  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5032  */
5033 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5034 {
5035   
5036   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5037   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5038   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5039 }
5040
5041 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5042 {
5043   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5044   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5045   //
5046   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5047   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5048   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5049   //
5050   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5051   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5052   DataArrayInt *conn1D=0,*conn1DI=0;
5053   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5054   DataArrayDouble *coordsTmp=0;
5055   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5056   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5057   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5058   const int *c1DPtr=conn1D->begin();
5059   const int *c1DIPtr=conn1DI->begin();
5060   int nbOfCells=getNumberOfCells();
5061   const int *cPtr=_nodal_connec->getConstPointer();
5062   const int *icPtr=_nodal_connec_index->getConstPointer();
5063   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5064   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5065     {
5066       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5067       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5068       if(!cm.isQuadratic())
5069         {
5070           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5071           types.insert(typ2); newConn->pushBackSilent(typ2);
5072           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5073           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5074             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5075           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5076           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5077           newConnI->pushBackSilent(lastVal);
5078           ret->pushBackSilent(i);
5079         }
5080       else
5081         {
5082           types.insert(typ);
5083           lastVal+=(icPtr[1]-icPtr[0]);
5084           newConnI->pushBackSilent(lastVal);
5085           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5086         }
5087     }
5088   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5089   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5090   return ret.retn();
5091 }
5092
5093 /*!
5094  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5095  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5096  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5097  */
5098 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5099 {
5100   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5101   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5102   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5103 }
5104
5105 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5106 {
5107   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5108   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5109   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5110   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5111   //
5112   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5113   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5114   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5115   //
5116   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5117   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5118   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5119   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5120   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5121   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5122   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5123   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5124   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5125   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5126   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5127   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5128   int nbOfCells=getNumberOfCells();
5129   const int *cPtr=_nodal_connec->getConstPointer();
5130   const int *icPtr=_nodal_connec_index->getConstPointer();
5131   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5132   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5133     {
5134       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5135       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5136       if(!cm.isQuadratic())
5137         {
5138           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5139           if(typ2==INTERP_KERNEL::NORM_ERROR)
5140             {
5141               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5142               throw INTERP_KERNEL::Exception(oss.str().c_str());
5143             }
5144           types.insert(typ2); newConn->pushBackSilent(typ2);
5145           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5146           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5147             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5148           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5149             {
5150               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5151               int tmpPos=newConn->getNumberOfTuples();
5152               newConn->pushBackSilent(nodeId2);
5153               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5154             }
5155           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5156           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5157           newConnI->pushBackSilent(lastVal);
5158           ret->pushBackSilent(i);
5159         }
5160       else
5161         {
5162           types.insert(typ);
5163           lastVal+=(icPtr[1]-icPtr[0]);
5164           newConnI->pushBackSilent(lastVal);
5165           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5166         }
5167     }
5168   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5169   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5170   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5171   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5172   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5173   int *c=newConn->getPointer();
5174   const int *cI(newConnI->begin());
5175   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5176     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5177   offset=coordsTmp2Safe->getNumberOfTuples();
5178   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5179     c[cI[(*elt)+1]-1]+=offset;
5180   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5181   return ret.retn();
5182 }
5183
5184 /*!
5185  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5186  * so that the number of cells remains the same. Quadratic faces are converted to
5187  * polygons. This method works only for 2D meshes in
5188  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5189  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5190  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5191  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5192  *         a polylinized edge constituting the input polygon.
5193  *  \throw If the coordinates array is not set.
5194  *  \throw If the nodal connectivity of cells is not defined.
5195  *  \throw If \a this->getMeshDimension() != 2.
5196  *  \throw If \a this->getSpaceDimension() != 2.
5197  */
5198 void MEDCouplingUMesh::tessellate2D(double eps)
5199 {
5200   checkFullyDefined();
5201   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5202     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5203   double epsa=fabs(eps);
5204   if(epsa<std::numeric_limits<double>::min())
5205     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 !");
5206   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5207   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5208   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5210   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5211   revDesc1=0; revDescIndx1=0;
5212   mDesc->tessellate2DCurve(eps);
5213   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5214   setCoords(mDesc->getCoords());
5215 }
5216
5217 /*!
5218  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5219  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5220  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5221  *         a sub-divided edge.
5222  *  \throw If the coordinates array is not set.
5223  *  \throw If the nodal connectivity of cells is not defined.
5224  *  \throw If \a this->getMeshDimension() != 1.
5225  *  \throw If \a this->getSpaceDimension() != 2.
5226  */
5227 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5228 {
5229   checkFullyDefined();
5230   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5231     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5232   double epsa=fabs(eps);
5233   if(epsa<std::numeric_limits<double>::min())
5234     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 !");
5235   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5236   int nbCells=getNumberOfCells();
5237   int nbNodes=getNumberOfNodes();
5238   const int *conn=_nodal_connec->getConstPointer();
5239   const int *connI=_nodal_connec_index->getConstPointer();
5240   const double *coords=_coords->getConstPointer();
5241   std::vector<double> addCoo;
5242   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5243   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5244   newConnI->alloc(nbCells+1,1);
5245   int *newConnIPtr=newConnI->getPointer();
5246   *newConnIPtr=0;
5247   int tmp1[3];
5248   INTERP_KERNEL::Node *tmp2[3];
5249   std::set<INTERP_KERNEL::NormalizedCellType> types;
5250   for(int i=0;i<nbCells;i++,newConnIPtr++)
5251     {
5252       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5253       if(cm.isQuadratic())
5254         {//assert(connI[i+1]-connI[i]-1==3)
5255           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5256           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5257           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5258           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5259           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5260           if(eac)
5261             {
5262               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5263               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5264               delete eac;
5265               newConnIPtr[1]=(int)newConn.size();
5266             }
5267           else
5268             {
5269               types.insert(INTERP_KERNEL::NORM_SEG2);
5270               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5271               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5272               newConnIPtr[1]=newConnIPtr[0]+3;
5273             }
5274         }
5275       else
5276         {
5277           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5278           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5279           newConnIPtr[1]=newConnIPtr[0]+3;
5280         }
5281     }
5282   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5283     return ;
5284   _types=types;
5285   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5286   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5287   newConnArr->alloc((int)newConn.size(),1);
5288   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5289   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5290   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5291   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5292   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5293   std::copy(addCoo.begin(),addCoo.end(),work);
5294   DataArrayDouble::SetArrayIn(newCoords,_coords);
5295   updateTime();
5296 }
5297
5298 /*!
5299  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5300  * In addition, returns an array mapping new cells to old ones. <br>
5301  * This method typically increases the number of cells in \a this mesh
5302  * but the number of nodes remains \b unchanged.
5303  * That's why the 3D splitting policies
5304  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5305  *  \param [in] policy - specifies a pattern used for splitting.
5306  * The semantic of \a policy is:
5307  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5308  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5309  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5310  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5311  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5312  *          an id of old cell producing it. The caller is to delete this array using
5313  *         decrRef() as it is no more needed. 
5314  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5315  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5316  *          and \a this->getMeshDimension() != 3. 
5317  *  \throw If \a policy is not one of the four discussed above.
5318  *  \throw If the nodal connectivity of cells is not defined.
5319  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5320  */
5321 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5322 {
5323   switch(policy)
5324     {
5325     case 0:
5326       return simplexizePol0();
5327     case 1:
5328       return simplexizePol1();
5329     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5330       return simplexizePlanarFace5();
5331     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5332       return simplexizePlanarFace6();
5333     default:
5334       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)");
5335     }
5336 }
5337
5338 /*!
5339  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5340  * - 1D: INTERP_KERNEL::NORM_SEG2
5341  * - 2D: INTERP_KERNEL::NORM_TRI3
5342  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5343  *
5344  * This method is useful for users that need to use P1 field services as
5345  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5346  * All these methods need mesh support containing only simplex cells.
5347  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5348  *  \throw If the coordinates array is not set.
5349  *  \throw If the nodal connectivity of cells is not defined.
5350  *  \throw If \a this->getMeshDimension() < 1.
5351  */
5352 bool MEDCouplingUMesh::areOnlySimplexCells() const
5353 {
5354   checkFullyDefined();
5355   int mdim=getMeshDimension();
5356   if(mdim<1 || mdim>3)
5357     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5358   int nbCells=getNumberOfCells();
5359   const int *conn=_nodal_connec->getConstPointer();
5360   const int *connI=_nodal_connec_index->getConstPointer();
5361   for(int i=0;i<nbCells;i++)
5362     {
5363       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5364       if(!cm.isSimplex())
5365         return false;
5366     }
5367   return true;
5368 }
5369
5370 /*!
5371  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5372  */
5373 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5374 {
5375   checkConnectivityFullyDefined();
5376   if(getMeshDimension()!=2)
5377     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5378   int nbOfCells=getNumberOfCells();
5379   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5380   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5381   ret->alloc(nbOfCells+nbOfCutCells,1);
5382   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5383   int *retPt=ret->getPointer();
5384   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5385   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5386   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5387   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5388   int *pt=newConn->getPointer();
5389   int *ptI=newConnI->getPointer();
5390   ptI[0]=0;
5391   const int *oldc=_nodal_connec->getConstPointer();
5392   const int *ci=_nodal_connec_index->getConstPointer();
5393   for(int i=0;i<nbOfCells;i++,ci++)
5394     {
5395       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5396         {
5397           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5398                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5399           pt=std::copy(tmp,tmp+8,pt);
5400           ptI[1]=ptI[0]+4;
5401           ptI[2]=ptI[0]+8;
5402           *retPt++=i;
5403           *retPt++=i;
5404           ptI+=2;
5405         }
5406       else
5407         {
5408           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5409           ptI[1]=ptI[0]+ci[1]-ci[0];
5410           ptI++;
5411           *retPt++=i;
5412         }
5413     }
5414   _nodal_connec->decrRef();
5415   _nodal_connec=newConn.retn();
5416   _nodal_connec_index->decrRef();
5417   _nodal_connec_index=newConnI.retn();
5418   computeTypes();
5419   updateTime();
5420   return ret.retn();
5421 }
5422
5423 /*!
5424  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5425  */
5426 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5427 {
5428   checkConnectivityFullyDefined();
5429   if(getMeshDimension()!=2)
5430     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5431   int nbOfCells=getNumberOfCells();
5432   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5433   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5434   ret->alloc(nbOfCells+nbOfCutCells,1);
5435   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5436   int *retPt=ret->getPointer();
5437   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5438   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5439   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5440   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5441   int *pt=newConn->getPointer();
5442   int *ptI=newConnI->getPointer();
5443   ptI[0]=0;
5444   const int *oldc=_nodal_connec->getConstPointer();
5445   const int *ci=_nodal_connec_index->getConstPointer();
5446   for(int i=0;i<nbOfCells;i++,ci++)
5447     {
5448       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5449         {
5450           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5451                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5452           pt=std::copy(tmp,tmp+8,pt);
5453           ptI[1]=ptI[0]+4;
5454           ptI[2]=ptI[0]+8;
5455           *retPt++=i;
5456           *retPt++=i;
5457           ptI+=2;
5458         }
5459       else
5460         {
5461           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5462           ptI[1]=ptI[0]+ci[1]-ci[0];
5463           ptI++;
5464           *retPt++=i;
5465         }
5466     }
5467   _nodal_connec->decrRef();
5468   _nodal_connec=newConn.retn();
5469   _nodal_connec_index->decrRef();
5470   _nodal_connec_index=newConnI.retn();
5471   computeTypes();
5472   updateTime();
5473   return ret.retn();
5474 }
5475
5476 /*!
5477  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5478  */
5479 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5480 {
5481   checkConnectivityFullyDefined();
5482   if(getMeshDimension()!=3)
5483     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5484   int nbOfCells=getNumberOfCells();
5485   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5486   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5487   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5488   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5489   int *retPt=ret->getPointer();
5490   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5491   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5492   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5493   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5494   int *pt=newConn->getPointer();
5495   int *ptI=newConnI->getPointer();
5496   ptI[0]=0;
5497   const int *oldc=_nodal_connec->getConstPointer();
5498   const int *ci=_nodal_connec_index->getConstPointer();
5499   for(int i=0;i<nbOfCells;i++,ci++)
5500     {
5501       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5502         {
5503           for(int j=0;j<5;j++,pt+=5,ptI++)
5504             {
5505               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5506               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];
5507               *retPt++=i;
5508               ptI[1]=ptI[0]+5;
5509             }
5510         }
5511       else
5512         {
5513           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5514           ptI[1]=ptI[0]+ci[1]-ci[0];
5515           ptI++;
5516           *retPt++=i;
5517         }
5518     }
5519   _nodal_connec->decrRef();
5520   _nodal_connec=newConn.retn();
5521   _nodal_connec_index->decrRef();
5522   _nodal_connec_index=newConnI.retn();
5523   computeTypes();
5524   updateTime();
5525   return ret.retn();
5526 }
5527
5528 /*!
5529  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5530  */
5531 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5532 {
5533   checkConnectivityFullyDefined();
5534   if(getMeshDimension()!=3)
5535     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5536   int nbOfCells=getNumberOfCells();
5537   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5538   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5539   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5540   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5541   int *retPt=ret->getPointer();
5542   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5543   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5544   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5545   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5546   int *pt=newConn->getPointer();
5547   int *ptI=newConnI->getPointer();
5548   ptI[0]=0;
5549   const int *oldc=_nodal_connec->getConstPointer();
5550   const int *ci=_nodal_connec_index->getConstPointer();
5551   for(int i=0;i<nbOfCells;i++,ci++)
5552     {
5553       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5554         {
5555           for(int j=0;j<6;j++,pt+=5,ptI++)
5556             {
5557               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5558               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];
5559               *retPt++=i;
5560               ptI[1]=ptI[0]+5;
5561             }
5562         }
5563       else
5564         {
5565           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5566           ptI[1]=ptI[0]+ci[1]-ci[0];
5567           ptI++;
5568           *retPt++=i;
5569         }
5570     }
5571   _nodal_connec->decrRef();
5572   _nodal_connec=newConn.retn();
5573   _nodal_connec_index->decrRef();
5574   _nodal_connec_index=newConnI.retn();
5575   computeTypes();
5576   updateTime();
5577   return ret.retn();
5578 }
5579
5580 /*!
5581  * 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.
5582  * This method completly ignore coordinates.
5583  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5584  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5585  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5586  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5587  */
5588 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5589 {
5590   checkFullyDefined();
5591   if(getMeshDimension()!=2)
5592     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5593   int nbOfCells=getNumberOfCells();
5594   int *connI=_nodal_connec_index->getPointer();
5595   int newConnLgth=0;
5596   for(int i=0;i<nbOfCells;i++,connI++)
5597     {
5598       int offset=descIndex[i];
5599       int nbOfEdges=descIndex[i+1]-offset;
5600       //
5601       bool ddirect=desc[offset+nbOfEdges-1]>0;
5602       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5603       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5604       for(int j=0;j<nbOfEdges;j++)
5605         {
5606           bool direct=desc[offset+j]>0;
5607           int edgeId=std::abs(desc[offset+j])-1;
5608           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5609             {
5610               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5611               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5612               int ref2=direct?id1:id2;
5613               if(ref==ref2)
5614                 {
5615                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5616                   newConnLgth+=nbOfSubNodes-1;
5617                   ref=direct?id2:id1;
5618                 }
5619               else
5620                 {
5621                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5622                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5623                 }
5624             }
5625           else
5626             {
5627               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5628             }
5629         }
5630       newConnLgth++;//+1 is for cell type
5631       connI[1]=newConnLgth;
5632     }
5633   //
5634   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5635   newConn->alloc(newConnLgth,1);
5636   int *work=newConn->getPointer();
5637   for(int i=0;i<nbOfCells;i++)
5638     {
5639       *work++=INTERP_KERNEL::NORM_POLYGON;
5640       int offset=descIndex[i];
5641       int nbOfEdges=descIndex[i+1]-offset;
5642       for(int j=0;j<nbOfEdges;j++)
5643         {
5644           bool direct=desc[offset+j]>0;
5645           int edgeId=std::abs(desc[offset+j])-1;
5646           if(direct)
5647             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5648           else
5649             {
5650               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5651               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5652               work=std::copy(it,it+nbOfSubNodes-1,work);
5653             }
5654         }
5655     }
5656   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5657   _types.clear();
5658   if(nbOfCells>0)
5659     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5660 }
5661
5662 /*!
5663  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5664  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5665  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5666  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5667  * so it can be useful to call mergeNodes() before calling this method.
5668  *  \throw If \a this->getMeshDimension() <= 1.
5669  *  \throw If the coordinates array is not set.
5670  *  \throw If the nodal connectivity of cells is not defined.
5671  */
5672 void MEDCouplingUMesh::convertDegeneratedCells()
5673 {
5674   checkFullyDefined();
5675   if(getMeshDimension()<=1)
5676     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5677   int nbOfCells=getNumberOfCells();
5678   if(nbOfCells<1)
5679     return ;
5680   int initMeshLgth=getMeshLength();
5681   int *conn=_nodal_connec->getPointer();
5682   int *index=_nodal_connec_index->getPointer();
5683   int posOfCurCell=0;
5684   int newPos=0;
5685   int lgthOfCurCell;
5686   for(int i=0;i<nbOfCells;i++)
5687     {
5688       lgthOfCurCell=index[i+1]-posOfCurCell;
5689       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5690       int newLgth;
5691       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5692                                                                                                      conn+newPos+1,newLgth);
5693       conn[newPos]=newType;
5694       newPos+=newLgth+1;
5695       posOfCurCell=index[i+1];
5696       index[i+1]=newPos;
5697     }
5698   if(newPos!=initMeshLgth)
5699     _nodal_connec->reAlloc(newPos);
5700   computeTypes();
5701 }
5702
5703 /*!
5704  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5705  * A cell is considered to be oriented correctly if an angle between its
5706  * normal vector and a given vector is less than \c PI / \c 2.
5707  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5708  *         cells. 
5709  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5710  *         checked.
5711  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5712  *         is not cleared before filling in.
5713  *  \throw If \a this->getMeshDimension() != 2.
5714  *  \throw If \a this->getSpaceDimension() != 3.
5715  *
5716  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5717  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5718  */
5719 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5720 {
5721   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5722     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5723   int nbOfCells=getNumberOfCells();
5724   const int *conn=_nodal_connec->getConstPointer();
5725   const int *connI=_nodal_connec_index->getConstPointer();
5726   const double *coordsPtr=_coords->getConstPointer();
5727   for(int i=0;i<nbOfCells;i++)
5728     {
5729       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5730       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5731         {
5732           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5733           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5734             cells.push_back(i);
5735         }
5736     }
5737 }
5738
5739 /*!
5740  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5741  * considered to be oriented correctly if an angle between its normal vector and a
5742  * given vector is less than \c PI / \c 2. 
5743  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5744  *         cells. 
5745  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5746  *         checked.
5747  *  \throw If \a this->getMeshDimension() != 2.
5748  *  \throw If \a this->getSpaceDimension() != 3.
5749  *
5750  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5751  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5752  */
5753 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5754 {
5755   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5756     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5757   int nbOfCells=getNumberOfCells();
5758   int *conn=_nodal_connec->getPointer();
5759   const int *connI=_nodal_connec_index->getConstPointer();
5760   const double *coordsPtr=_coords->getConstPointer();
5761   bool isModified=false;
5762   for(int i=0;i<nbOfCells;i++)
5763     {
5764       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5765       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5766         {
5767           bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5768           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5769             {
5770               isModified=true;
5771               if(!isQuadratic)
5772                 {
5773                   std::vector<int> tmp(connI[i+1]-connI[i]-2);
5774                   std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5775                   std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5776                 }
5777               else
5778                 {
5779                   int sz(((int)(connI[i+1]-connI[i]-1))/2);
5780                   std::vector<int> tmp0(sz-1),tmp1(sz);
5781                   std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5782                   std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5783                   std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5784                   std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5785                 }
5786             }
5787         }
5788     }
5789   if(isModified)
5790     _nodal_connec->declareAsNew();
5791   updateTime();
5792 }
5793
5794 /*!
5795  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5796  * oriented facets. The normal vector of the facet should point out of the cell.
5797  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5798  *         is not cleared before filling in.
5799  *  \throw If \a this->getMeshDimension() != 3.
5800  *  \throw If \a this->getSpaceDimension() != 3.
5801  *  \throw If the coordinates array is not set.
5802  *  \throw If the nodal connectivity of cells is not defined.
5803  *
5804  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5805  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5806  */
5807 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5808 {
5809   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5810     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5811   int nbOfCells=getNumberOfCells();
5812   const int *conn=_nodal_connec->getConstPointer();
5813   const int *connI=_nodal_connec_index->getConstPointer();
5814   const double *coordsPtr=_coords->getConstPointer();
5815   for(int i=0;i<nbOfCells;i++)
5816     {
5817       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5818       if(type==INTERP_KERNEL::NORM_POLYHED)
5819         {
5820           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5821             cells.push_back(i);
5822         }
5823     }
5824 }
5825
5826 /*!
5827  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5828  * out of the cell. 
5829  *  \throw If \a this->getMeshDimension() != 3.
5830  *  \throw If \a this->getSpaceDimension() != 3.
5831  *  \throw If the coordinates array is not set.
5832  *  \throw If the nodal connectivity of cells is not defined.
5833  *  \throw If the reparation fails.
5834  *
5835  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5836  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5837  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5838  */
5839 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5840 {
5841   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5842     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5843   int nbOfCells=getNumberOfCells();
5844   int *conn=_nodal_connec->getPointer();
5845   const int *connI=_nodal_connec_index->getConstPointer();
5846   const double *coordsPtr=_coords->getConstPointer();
5847   for(int i=0;i<nbOfCells;i++)
5848     {
5849       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5850       if(type==INTERP_KERNEL::NORM_POLYHED)
5851         {
5852           try
5853             {
5854               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5855                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5856             }
5857           catch(INTERP_KERNEL::Exception& e)
5858             {
5859               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5860               throw INTERP_KERNEL::Exception(oss.str().c_str());
5861             }
5862         }
5863     }
5864   updateTime();
5865 }
5866
5867 /*!
5868  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5869  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5870  * according to which the first facet of the cell should be oriented to have the normal vector
5871  * pointing out of cell.
5872  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5873  *         cells. The caller is to delete this array using decrRef() as it is no more
5874  *         needed. 
5875  *  \throw If \a this->getMeshDimension() != 3.
5876  *  \throw If \a this->getSpaceDimension() != 3.
5877  *  \throw If the coordinates array is not set.
5878  *  \throw If the nodal connectivity of cells is not defined.
5879  *
5880  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5881  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5882  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5883  */
5884 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5885 {
5886   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5887   if(getMeshDimension()!=3)
5888     throw INTERP_KERNEL::Exception(msg);
5889   int spaceDim=getSpaceDimension();
5890   if(spaceDim!=3)
5891     throw INTERP_KERNEL::Exception(msg);
5892   //
5893   int nbOfCells=getNumberOfCells();
5894   int *conn=_nodal_connec->getPointer();
5895   const int *connI=_nodal_connec_index->getConstPointer();
5896   const double *coo=getCoords()->getConstPointer();
5897   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5898   for(int i=0;i<nbOfCells;i++)
5899     {
5900       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5901       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5902         {
5903           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5904             {
5905               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5906               cells->pushBackSilent(i);
5907             }
5908         }
5909     }
5910   return cells.retn();
5911 }
5912
5913 /*!
5914  * This method is a faster method to correct orientation of all 3D cells in \a this.
5915  * 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.
5916  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5917  * 
5918  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5919  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5920  */
5921 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
5922 {
5923   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5924     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5925   int nbOfCells=getNumberOfCells();
5926   int *conn=_nodal_connec->getPointer();
5927   const int *connI=_nodal_connec_index->getConstPointer();
5928   const double *coordsPtr=_coords->getConstPointer();
5929   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5930   for(int i=0;i<nbOfCells;i++)
5931     {
5932       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5933       switch(type)
5934         {
5935         case INTERP_KERNEL::NORM_TETRA4:
5936           {
5937             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5938               {
5939                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5940                 ret->pushBackSilent(i);
5941               }
5942             break;
5943           }
5944         case INTERP_KERNEL::NORM_PYRA5:
5945           {
5946             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5947               {
5948                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5949                 ret->pushBackSilent(i);
5950               }
5951             break;
5952           }
5953         case INTERP_KERNEL::NORM_PENTA6:
5954         case INTERP_KERNEL::NORM_HEXA8:
5955         case INTERP_KERNEL::NORM_HEXGP12:
5956           {
5957             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5958               {
5959                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5960                 ret->pushBackSilent(i);
5961               }
5962             break;
5963           }
5964         case INTERP_KERNEL::NORM_POLYHED:
5965           {
5966             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5967               {
5968                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5969                 ret->pushBackSilent(i);
5970               }
5971             break;
5972           }
5973         default:
5974           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 !");
5975         }
5976     }
5977   updateTime();
5978   return ret.retn();
5979 }
5980
5981 /*!
5982  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5983  * If it is not the case an exception will be thrown.
5984  * This method is fast because the first cell of \a this is used to compute the plane.
5985  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5986  * \param pos output of size at least 3 used to store a point owned of searched plane.
5987  */
5988 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
5989 {
5990   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5991     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5992   const int *conn=_nodal_connec->getConstPointer();
5993   const int *connI=_nodal_connec_index->getConstPointer();
5994   const double *coordsPtr=_coords->getConstPointer();
5995   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5996   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5997 }
5998
5999 /*!
6000  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6001  * cells. Currently cells of the following types are treated:
6002  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6003  * For a cell of other type an exception is thrown.
6004  * Space dimension of a 2D mesh can be either 2 or 3.
6005  * The Edge Ratio of a cell \f$t\f$ is: 
6006  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6007  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6008  *  the smallest edge lengths of \f$t\f$.
6009  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6010  *          cells and one time, lying on \a this mesh. The caller is to delete this
6011  *          field using decrRef() as it is no more needed. 
6012  *  \throw If the coordinates array is not set.
6013  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6014  *  \throw If the connectivity data array has more than one component.
6015  *  \throw If the connectivity data array has a named component.
6016  *  \throw If the connectivity index data array has more than one component.
6017  *  \throw If the connectivity index data array has a named component.
6018  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6019  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6020  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6021  */
6022 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6023 {
6024   checkCoherency();
6025   int spaceDim=getSpaceDimension();
6026   int meshDim=getMeshDimension();
6027   if(spaceDim!=2 && spaceDim!=3)
6028     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6029   if(meshDim!=2 && meshDim!=3)
6030     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6031   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6032   ret->setMesh(this);
6033   int nbOfCells=getNumberOfCells();
6034   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6035   arr->alloc(nbOfCells,1);
6036   double *pt=arr->getPointer();
6037   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6038   const int *conn=_nodal_connec->getConstPointer();
6039   const int *connI=_nodal_connec_index->getConstPointer();
6040   const double *coo=_coords->getConstPointer();
6041   double tmp[12];
6042   for(int i=0;i<nbOfCells;i++,pt++)
6043     {
6044       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6045       switch(t)
6046         {
6047           case INTERP_KERNEL::NORM_TRI3:
6048             {
6049               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6050               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6051               break;
6052             }
6053           case INTERP_KERNEL::NORM_QUAD4:
6054             {
6055               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6056               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6057               break;
6058             }
6059           case INTERP_KERNEL::NORM_TETRA4:
6060             {
6061               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6062               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6063               break;
6064             }
6065         default:
6066           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6067         }
6068       conn+=connI[i+1]-connI[i];
6069     }
6070   ret->setName("EdgeRatio");
6071   ret->synchronizeTimeWithSupport();
6072   return ret.retn();
6073 }
6074
6075 /*!
6076  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6077  * cells. Currently cells of the following types are treated:
6078  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6079  * For a cell of other type an exception is thrown.
6080  * Space dimension of a 2D mesh can be either 2 or 3.
6081  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6082  *          cells and one time, lying on \a this mesh. The caller is to delete this
6083  *          field using decrRef() as it is no more needed. 
6084  *  \throw If the coordinates array is not set.
6085  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6086  *  \throw If the connectivity data array has more than one component.
6087  *  \throw If the connectivity data array has a named component.
6088  *  \throw If the connectivity index data array has more than one component.
6089  *  \throw If the connectivity index data array has a named component.
6090  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6091  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6092  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6093  */
6094 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6095 {
6096   checkCoherency();
6097   int spaceDim=getSpaceDimension();
6098   int meshDim=getMeshDimension();
6099   if(spaceDim!=2 && spaceDim!=3)
6100     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6101   if(meshDim!=2 && meshDim!=3)
6102     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6103   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6104   ret->setMesh(this);
6105   int nbOfCells=getNumberOfCells();
6106   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6107   arr->alloc(nbOfCells,1);
6108   double *pt=arr->getPointer();
6109   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6110   const int *conn=_nodal_connec->getConstPointer();
6111   const int *connI=_nodal_connec_index->getConstPointer();
6112   const double *coo=_coords->getConstPointer();
6113   double tmp[12];
6114   for(int i=0;i<nbOfCells;i++,pt++)
6115     {
6116       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6117       switch(t)
6118         {
6119           case INTERP_KERNEL::NORM_TRI3:
6120             {
6121               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6122               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6123               break;
6124             }
6125           case INTERP_KERNEL::NORM_QUAD4:
6126             {
6127               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6128               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6129               break;
6130             }
6131           case INTERP_KERNEL::NORM_TETRA4:
6132             {
6133               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6134               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6135               break;
6136             }
6137         default:
6138           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6139         }
6140       conn+=connI[i+1]-connI[i];
6141     }
6142   ret->setName("AspectRatio");
6143   ret->synchronizeTimeWithSupport();
6144   return ret.retn();
6145 }
6146
6147 /*!
6148  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6149  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6150  * treated: INTERP_KERNEL::NORM_QUAD4.
6151  * For a cell of other type an exception is thrown.
6152  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6153  *          cells and one time, lying on \a this mesh. The caller is to delete this
6154  *          field using decrRef() as it is no more needed. 
6155  *  \throw If the coordinates array is not set.
6156  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6157  *  \throw If the connectivity data array has more than one component.
6158  *  \throw If the connectivity data array has a named component.
6159  *  \throw If the connectivity index data array has more than one component.
6160  *  \throw If the connectivity index data array has a named component.
6161  *  \throw If \a this->getMeshDimension() != 2.
6162  *  \throw If \a this->getSpaceDimension() != 3.
6163  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6164  */
6165 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6166 {
6167   checkCoherency();
6168   int spaceDim=getSpaceDimension();
6169   int meshDim=getMeshDimension();
6170   if(spaceDim!=3)
6171     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6172   if(meshDim!=2)
6173     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6174   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6175   ret->setMesh(this);
6176   int nbOfCells=getNumberOfCells();
6177   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6178   arr->alloc(nbOfCells,1);
6179   double *pt=arr->getPointer();
6180   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6181   const int *conn=_nodal_connec->getConstPointer();
6182   const int *connI=_nodal_connec_index->getConstPointer();
6183   const double *coo=_coords->getConstPointer();
6184   double tmp[12];
6185   for(int i=0;i<nbOfCells;i++,pt++)
6186     {
6187       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6188       switch(t)
6189         {
6190           case INTERP_KERNEL::NORM_QUAD4:
6191             {
6192               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6193               *pt=INTERP_KERNEL::quadWarp(tmp);
6194               break;
6195             }
6196         default:
6197           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6198         }
6199       conn+=connI[i+1]-connI[i];
6200     }
6201   ret->setName("Warp");
6202   ret->synchronizeTimeWithSupport();
6203   return ret.retn();
6204 }
6205
6206
6207 /*!
6208  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6209  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6210  * treated: INTERP_KERNEL::NORM_QUAD4.
6211  * For a cell of other type an exception is thrown.
6212  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6213  *          cells and one time, lying on \a this mesh. The caller is to delete this
6214  *          field using decrRef() as it is no more needed. 
6215  *  \throw If the coordinates array is not set.
6216  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6217  *  \throw If the connectivity data array has more than one component.
6218  *  \throw If the connectivity data array has a named component.
6219  *  \throw If the connectivity index data array has more than one component.
6220  *  \throw If the connectivity index data array has a named component.
6221  *  \throw If \a this->getMeshDimension() != 2.
6222  *  \throw If \a this->getSpaceDimension() != 3.
6223  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6224  */
6225 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6226 {
6227   checkCoherency();
6228   int spaceDim=getSpaceDimension();
6229   int meshDim=getMeshDimension();
6230   if(spaceDim!=3)
6231     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6232   if(meshDim!=2)
6233     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6234   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6235   ret->setMesh(this);
6236   int nbOfCells=getNumberOfCells();
6237   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6238   arr->alloc(nbOfCells,1);
6239   double *pt=arr->getPointer();
6240   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6241   const int *conn=_nodal_connec->getConstPointer();
6242   const int *connI=_nodal_connec_index->getConstPointer();
6243   const double *coo=_coords->getConstPointer();
6244   double tmp[12];
6245   for(int i=0;i<nbOfCells;i++,pt++)
6246     {
6247       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6248       switch(t)
6249         {
6250           case INTERP_KERNEL::NORM_QUAD4:
6251             {
6252               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6253               *pt=INTERP_KERNEL::quadSkew(tmp);
6254               break;
6255             }
6256         default:
6257           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6258         }
6259       conn+=connI[i+1]-connI[i];
6260     }
6261   ret->setName("Skew");
6262   ret->synchronizeTimeWithSupport();
6263   return ret.retn();
6264 }
6265
6266 /*!
6267  * This method aggregate the bbox of each cell and put it into bbox parameter.
6268  * 
6269  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6270  *                         For all other cases this input parameter is ignored.
6271  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6272  * 
6273  * \throw If \a this is not fully set (coordinates and connectivity).
6274  * \throw If a cell in \a this has no valid nodeId.
6275  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6276  */
6277 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6278 {
6279   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6280   if((mDim==3 && sDim==3) || (mDim==2 && sDim==3) || (mDim==1 && sDim==1) || ( mDim==1 && sDim==3))  // Compute refined boundary box for quadratic elements only in 2D.
6281     return getBoundingBoxForBBTreeFast();
6282   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6283     {
6284       bool presenceOfQuadratic(false);
6285       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6286         {
6287           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6288           if(cm.isQuadratic())
6289             presenceOfQuadratic=true;
6290         }
6291       if(!presenceOfQuadratic)
6292         return getBoundingBoxForBBTreeFast();
6293       if(mDim==2 && sDim==2)
6294         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6295       else
6296         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6297     }
6298   throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree : Managed dimensions are (mDim=1,sDim=1), (mDim=1,sDim=2), (mDim=1,sDim=3), (mDim=2,sDim=2), (mDim=2,sDim=3) and (mDim=3,sDim=3) !");
6299 }
6300
6301 /*!
6302  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6303  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6304  * 
6305  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6306  * 
6307  * \throw If \a this is not fully set (coordinates and connectivity).
6308  * \throw If a cell in \a this has no valid nodeId.
6309  */
6310 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6311 {
6312   checkFullyDefined();
6313   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6314   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6315   double *bbox(ret->getPointer());
6316   for(int i=0;i<nbOfCells*spaceDim;i++)
6317     {
6318       bbox[2*i]=std::numeric_limits<double>::max();
6319       bbox[2*i+1]=-std::numeric_limits<double>::max();
6320     }
6321   const double *coordsPtr(_coords->getConstPointer());
6322   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6323   for(int i=0;i<nbOfCells;i++)
6324     {
6325       int offset=connI[i]+1;
6326       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6327       for(int j=0;j<nbOfNodesForCell;j++)
6328         {
6329           int nodeId=conn[offset+j];
6330           if(nodeId>=0 && nodeId<nbOfNodes)
6331             {
6332               for(int k=0;k<spaceDim;k++)
6333                 {
6334                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6335                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6336                 }
6337               kk++;
6338             }
6339         }
6340       if(kk==0)
6341         {
6342           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6343           throw INTERP_KERNEL::Exception(oss.str().c_str());
6344         }
6345     }
6346   return ret.retn();
6347 }
6348
6349 /*!
6350  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6351  * useful for 2D meshes having quadratic cells
6352  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6353  * the two extremities of the arc of circle).
6354  * 
6355  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6356  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6357  * \throw If \a this is not fully defined.
6358  * \throw If \a this is not a mesh with meshDimension equal to 2.
6359  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6360  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6361  */
6362 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6363 {
6364   checkFullyDefined();
6365   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6366   if(spaceDim!=2 || spaceDim!=2)
6367     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic : This method should be applied on mesh with mesh dimension equal to 2 and space dimension also equal to 2!");
6368   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6369   double *bbox(ret->getPointer());
6370   const double *coords(_coords->getConstPointer());
6371   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6372   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6373     {
6374       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6375       int sz(connI[1]-connI[0]-1);
6376       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6377       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6378       INTERP_KERNEL::QuadraticPolygon *pol(0);
6379       for(int j=0;j<sz;j++)
6380         {
6381           int nodeId(conn[*connI+1+j]);
6382           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6383         }
6384       if(!cm.isQuadratic())
6385         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6386       else
6387         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6388       INTERP_KERNEL::Bounds b; pol->fillBounds(b); delete pol;
6389       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6390     }
6391   return ret.retn();
6392 }
6393
6394 /*!
6395  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6396  * useful for 2D meshes having quadratic cells
6397  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6398  * the two extremities of the arc of circle).
6399  * 
6400  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6401  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6402  * \throw If \a this is not fully defined.
6403  * \throw If \a this is not a mesh with meshDimension equal to 1.
6404  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6405  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6406  */
6407 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6408 {
6409   checkFullyDefined();
6410   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6411   if(spaceDim!=2 || spaceDim!=2)
6412     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic : This method should be applied on mesh with mesh dimension equal to 1 and space dimension also equal to 2!");
6413   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6414   double *bbox(ret->getPointer());
6415   const double *coords(_coords->getConstPointer());
6416   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6417   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6418     {
6419       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6420       int sz(connI[1]-connI[0]-1);
6421       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6422       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6423       INTERP_KERNEL::Edge *edge(0);
6424       for(int j=0;j<sz;j++)
6425         {
6426           int nodeId(conn[*connI+1+j]);
6427           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6428         }
6429       if(!cm.isQuadratic())
6430         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6431       else
6432         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6433       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6434       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6435     }
6436   return ret.retn();
6437 }
6438
6439 /// @cond INTERNAL
6440
6441 namespace ParaMEDMEMImpl
6442 {
6443   class ConnReader
6444   {
6445   public:
6446     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6447     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6448   private:
6449     const int *_conn;
6450     int _val;
6451   };
6452
6453   class ConnReader2
6454   {
6455   public:
6456     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6457     bool operator() (const int& pos) { return _conn[pos]==_val; }
6458   private:
6459     const int *_conn;
6460     int _val;
6461   };
6462 }
6463
6464 /// @endcond
6465
6466 /*!
6467  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6468  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6469  * \a this is composed in cell types.
6470  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6471  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6472  * This parameter is kept only for compatibility with other methode listed above.
6473  */
6474 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6475 {
6476   checkConnectivityFullyDefined();
6477   const int *conn=_nodal_connec->getConstPointer();
6478   const int *connI=_nodal_connec_index->getConstPointer();
6479   const int *work=connI;
6480   int nbOfCells=getNumberOfCells();
6481   std::size_t n=getAllGeoTypes().size();
6482   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6483   std::set<INTERP_KERNEL::NormalizedCellType> types;
6484   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6485     {
6486       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6487       if(types.find(typ)!=types.end())
6488         {
6489           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6490           oss << " is not contiguous !";
6491           throw INTERP_KERNEL::Exception(oss.str().c_str());
6492         }
6493       types.insert(typ);
6494       ret[3*i]=typ;
6495       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6496       ret[3*i+1]=(int)std::distance(work,work2);
6497       work=work2;
6498     }
6499   return ret;
6500 }
6501
6502 /*!
6503  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6504  * only for types cell, type node is not managed.
6505  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6506  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6507  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6508  * If 2 or more same geometric type is in \a code and exception is thrown too.
6509  *
6510  * This method firstly checks
6511  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6512  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6513  * an exception is thrown too.
6514  * 
6515  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6516  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6517  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6518  */
6519 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6520 {
6521   if(code.empty())
6522     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6523   std::size_t sz=code.size();
6524   std::size_t n=sz/3;
6525   if(sz%3!=0)
6526     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6527   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6528   int nb=0;
6529   bool isNoPflUsed=true;
6530   for(std::size_t i=0;i<n;i++)
6531     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6532       {
6533         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6534         nb+=code[3*i+1];
6535         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6536           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6537         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6538       }
6539   if(types.size()!=n)
6540     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6541   if(isNoPflUsed)
6542     {
6543       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6544         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6545       if(types.size()==_types.size())
6546         return 0;
6547     }
6548   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6549   ret->alloc(nb,1);
6550   int *retPtr=ret->getPointer();
6551   const int *connI=_nodal_connec_index->getConstPointer();
6552   const int *conn=_nodal_connec->getConstPointer();
6553   int nbOfCells=getNumberOfCells();
6554   const int *i=connI;
6555   int kk=0;
6556   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6557     {
6558       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6559       int offset=(int)std::distance(connI,i);
6560       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6561       int nbOfCellsOfCurType=(int)std::distance(i,j);
6562       if(code[3*kk+2]==-1)
6563         for(int k=0;k<nbOfCellsOfCurType;k++)
6564           *retPtr++=k+offset;
6565       else
6566         {
6567           int idInIdsPerType=code[3*kk+2];
6568           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6569             {
6570               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6571               if(zePfl)
6572                 {
6573                   zePfl->checkAllocated();
6574                   if(zePfl->getNumberOfComponents()==1)
6575                     {
6576                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6577                         {
6578                           if(*k>=0 && *k<nbOfCellsOfCurType)
6579                             *retPtr=(*k)+offset;
6580                           else
6581                             {
6582                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6583                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6584                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6585                             }
6586                         }
6587                     }
6588                   else
6589                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6590                 }
6591               else
6592                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6593             }
6594           else
6595             {
6596               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6597               oss << " should be in [0," << idsPerType.size() << ") !";
6598               throw INTERP_KERNEL::Exception(oss.str().c_str());
6599             }
6600         }
6601       i=j;
6602     }
6603   return ret.retn();
6604 }
6605
6606 /*!
6607  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6608  * 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.
6609  * 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.
6610  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6611  * 
6612  * \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.
6613  * \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,
6614  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6615  * \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.
6616  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6617  * \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
6618  */
6619 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6620 {
6621   if(!profile)
6622     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6623   if(profile->getNumberOfComponents()!=1)
6624     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6625   checkConnectivityFullyDefined();
6626   const int *conn=_nodal_connec->getConstPointer();
6627   const int *connI=_nodal_connec_index->getConstPointer();
6628   int nbOfCells=getNumberOfCells();
6629   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6630   std::vector<int> typeRangeVals(1);
6631   for(const int *i=connI;i!=connI+nbOfCells;)
6632     {
6633       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6634       if(std::find(types.begin(),types.end(),curType)!=types.end())
6635         {
6636           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6637         }
6638       types.push_back(curType);
6639       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6640       typeRangeVals.push_back((int)std::distance(connI,i));
6641     }
6642   //
6643   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6644   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6645   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6646   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6647   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6648   //
6649   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6650   code.resize(3*nbOfCastsFinal);
6651   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6652   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6653   for(int i=0;i<nbOfCastsFinal;i++)
6654     {
6655       int castId=castsPresent->getIJ(i,0);
6656       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6657       idsInPflPerType2.push_back(tmp3);
6658       code[3*i]=(int)types[castId];
6659       code[3*i+1]=tmp3->getNumberOfTuples();
6660       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6661       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6662         {
6663           tmp4->copyStringInfoFrom(*profile);
6664           idsPerType2.push_back(tmp4);
6665           code[3*i+2]=(int)idsPerType2.size()-1;
6666         }
6667       else
6668         {
6669           code[3*i+2]=-1;
6670         }
6671     }
6672   std::size_t sz2=idsInPflPerType2.size();
6673   idsInPflPerType.resize(sz2);
6674   for(std::size_t i=0;i<sz2;i++)
6675     {
6676       DataArrayInt *locDa=idsInPflPerType2[i];
6677       locDa->incrRef();
6678       idsInPflPerType[i]=locDa;
6679     }
6680   std::size_t sz=idsPerType2.size();
6681   idsPerType.resize(sz);
6682   for(std::size_t i=0;i<sz;i++)
6683     {
6684       DataArrayInt *locDa=idsPerType2[i];
6685       locDa->incrRef();
6686       idsPerType[i]=locDa;
6687     }
6688 }
6689
6690 /*!
6691  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6692  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6693  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6694  * 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.
6695  */
6696 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6697 {
6698   checkFullyDefined();
6699   nM1LevMesh->checkFullyDefined();
6700   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6701     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6702   if(_coords!=nM1LevMesh->getCoords())
6703     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6704   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6705   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6706   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6707   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6708   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6709   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6710   tmp->setConnectivity(tmp0,tmp1);
6711   tmp->renumberCells(ret0->getConstPointer(),false);
6712   revDesc=tmp->getNodalConnectivity();
6713   revDescIndx=tmp->getNodalConnectivityIndex();
6714   DataArrayInt *ret=0;
6715   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6716     {
6717       int tmp2;
6718       ret->getMaxValue(tmp2);
6719       ret->decrRef();
6720       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6721       throw INTERP_KERNEL::Exception(oss.str().c_str());
6722     }
6723   nM1LevMeshIds=ret;
6724   //
6725   revDesc->incrRef();
6726   revDescIndx->incrRef();
6727   ret1->incrRef();
6728   ret0->incrRef();
6729   meshnM1Old2New=ret0;
6730   return ret1;
6731 }
6732
6733 /*!
6734  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6735  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6736  * in "Old to New" mode.
6737  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6738  *          this array using decrRef() as it is no more needed.
6739  *  \throw If the nodal connectivity of cells is not defined.
6740  */
6741 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6742 {
6743   checkConnectivityFullyDefined();
6744   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6745   renumberCells(ret->getConstPointer(),false);
6746   return ret.retn();
6747 }
6748
6749 /*!
6750  * This methods checks that cells are sorted by their types.
6751  * This method makes asumption (no check) that connectivity is correctly set before calling.
6752  */
6753 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6754 {
6755   checkFullyDefined();
6756   const int *conn=_nodal_connec->getConstPointer();
6757   const int *connI=_nodal_connec_index->getConstPointer();
6758   int nbOfCells=getNumberOfCells();
6759   std::set<INTERP_KERNEL::NormalizedCellType> types;
6760   for(const int *i=connI;i!=connI+nbOfCells;)
6761     {
6762       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6763       if(types.find(curType)!=types.end())
6764         return false;
6765       types.insert(curType);
6766       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6767     }
6768   return true;
6769 }
6770
6771 /*!
6772  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6773  * The geometric type order is specified by MED file.
6774  * 
6775  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6776  */
6777 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6778 {
6779   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6780 }
6781
6782 /*!
6783  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6784  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6785  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6786  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6787  */
6788 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6789 {
6790   checkFullyDefined();
6791   const int *conn=_nodal_connec->getConstPointer();
6792   const int *connI=_nodal_connec_index->getConstPointer();
6793   int nbOfCells=getNumberOfCells();
6794   if(nbOfCells==0)
6795     return true;
6796   int lastPos=-1;
6797   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6798   for(const int *i=connI;i!=connI+nbOfCells;)
6799     {
6800       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6801       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6802       if(isTypeExists!=orderEnd)
6803         {
6804           int pos=(int)std::distance(orderBg,isTypeExists);
6805           if(pos<=lastPos)
6806             return false;
6807           lastPos=pos;
6808           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6809         }
6810       else
6811         {
6812           if(sg.find(curType)==sg.end())
6813             {
6814               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6815               sg.insert(curType);
6816             }
6817           else
6818             return false;
6819         }
6820     }
6821   return true;
6822 }
6823
6824 /*!
6825  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6826  * 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
6827  * 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'.
6828  */
6829 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6830 {
6831   checkConnectivityFullyDefined();
6832   int nbOfCells=getNumberOfCells();
6833   const int *conn=_nodal_connec->getConstPointer();
6834   const int *connI=_nodal_connec_index->getConstPointer();
6835   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6836   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6837   tmpa->alloc(nbOfCells,1);
6838   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6839   tmpb->fillWithZero();
6840   int *tmp=tmpa->getPointer();
6841   int *tmp2=tmpb->getPointer();
6842   for(const int *i=connI;i!=connI+nbOfCells;i++)
6843     {
6844       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6845       if(where!=orderEnd)
6846         {
6847           int pos=(int)std::distance(orderBg,where);
6848           tmp2[pos]++;
6849           tmp[std::distance(connI,i)]=pos;
6850         }
6851       else
6852         {
6853           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6854           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6855           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6856           throw INTERP_KERNEL::Exception(oss.str().c_str());
6857         }
6858     }
6859   nbPerType=tmpb.retn();
6860   return tmpa.retn();
6861 }
6862
6863 /*!
6864  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6865  *
6866  * \return a new object containing the old to new correspondance.
6867  *
6868  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6869  */
6870 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6871 {
6872   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6873 }
6874
6875 /*!
6876  * 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.
6877  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6878  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6879  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6880  */
6881 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6882 {
6883   DataArrayInt *nbPerType=0;
6884   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6885   nbPerType->decrRef();
6886   return tmpa->buildPermArrPerLevel();
6887 }
6888
6889 /*!
6890  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6891  * The number of cells remains unchanged after the call of this method.
6892  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6893  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6894  *
6895  * \return the array giving the correspondance old to new.
6896  */
6897 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6898 {
6899   checkFullyDefined();
6900   computeTypes();
6901   const int *conn=_nodal_connec->getConstPointer();
6902   const int *connI=_nodal_connec_index->getConstPointer();
6903   int nbOfCells=getNumberOfCells();
6904   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6905   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6906     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6907       {
6908         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6909         types.push_back(curType);
6910         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6911       }
6912   DataArrayInt *ret=DataArrayInt::New();
6913   ret->alloc(nbOfCells,1);
6914   int *retPtr=ret->getPointer();
6915   std::fill(retPtr,retPtr+nbOfCells,-1);
6916   int newCellId=0;
6917   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6918     {
6919       for(const int *i=connI;i!=connI+nbOfCells;i++)
6920         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6921           retPtr[std::distance(connI,i)]=newCellId++;
6922     }
6923   renumberCells(retPtr,false);
6924   return ret;
6925 }
6926
6927 /*!
6928  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6929  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6930  * This method makes asumption that connectivity is correctly set before calling.
6931  */
6932 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6933 {
6934   checkConnectivityFullyDefined();
6935   const int *conn=_nodal_connec->getConstPointer();
6936   const int *connI=_nodal_connec_index->getConstPointer();
6937   int nbOfCells=getNumberOfCells();
6938   std::vector<MEDCouplingUMesh *> ret;
6939   for(const int *i=connI;i!=connI+nbOfCells;)
6940     {
6941       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6942       int beginCellId=(int)std::distance(connI,i);
6943       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6944       int endCellId=(int)std::distance(connI,i);
6945       int sz=endCellId-beginCellId;
6946       int *cells=new int[sz];
6947       for(int j=0;j<sz;j++)
6948         cells[j]=beginCellId+j;
6949       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6950       delete [] cells;
6951       ret.push_back(m);
6952     }
6953   return ret;
6954 }
6955
6956 /*!
6957  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6958  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6959  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6960  *
6961  * \return a newly allocated instance, that the caller must manage.
6962  * \throw If \a this contains more than one geometric type.
6963  * \throw If the nodal connectivity of \a this is not fully defined.
6964  * \throw If the internal data is not coherent.
6965  */
6966 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
6967 {
6968   checkConnectivityFullyDefined();
6969     if(_types.size()!=1)
6970     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6971   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6972   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6973   ret->setCoords(getCoords());
6974   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6975   if(retC)
6976     {
6977       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6978       retC->setNodalConnectivity(c);
6979     }
6980   else
6981     {
6982       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6983       if(!retD)
6984         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6985       DataArrayInt *c=0,*ci=0;
6986       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6987       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6988       retD->setNodalConnectivity(cs,cis);
6989     }
6990   return ret.retn();
6991 }
6992
6993 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
6994 {
6995   checkConnectivityFullyDefined();
6996     if(_types.size()!=1)
6997     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6998   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6999   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7000   if(cm.isDynamic())
7001     {
7002       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7003       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7004       throw INTERP_KERNEL::Exception(oss.str().c_str());
7005     }
7006   int nbCells=getNumberOfCells();
7007   int typi=(int)typ;
7008   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7009   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7010   int *outPtr=connOut->getPointer();
7011   const int *conn=_nodal_connec->begin();
7012   const int *connI=_nodal_connec_index->begin();
7013   nbNodesPerCell++;
7014   for(int i=0;i<nbCells;i++,connI++)
7015     {
7016       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7017         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7018       else
7019         {
7020           std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : there something wrong in cell #" << i << " ! The type of cell is not those expected, or the length of nodal connectivity is not those expected (" << nbNodesPerCell-1 << ") !";
7021           throw INTERP_KERNEL::Exception(oss.str().c_str());
7022         }
7023     }
7024   return connOut.retn();
7025 }
7026
7027 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7028 {
7029   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7030   checkConnectivityFullyDefined();
7031   if(_types.size()!=1)
7032     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7033   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7034   if(lgth<nbCells)
7035     throw INTERP_KERNEL::Exception(msg0);
7036   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7037   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7038   int *cp(c->getPointer()),*cip(ci->getPointer());
7039   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7040   cip[0]=0;
7041   for(int i=0;i<nbCells;i++,cip++,incip++)
7042     {
7043       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7044       int delta(stop-strt);
7045       if(delta>=1)
7046         {
7047           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7048             cp=std::copy(incp+strt,incp+stop,cp);
7049           else
7050             throw INTERP_KERNEL::Exception(msg0);
7051         }
7052       else
7053         throw INTERP_KERNEL::Exception(msg0);
7054       cip[1]=cip[0]+delta;
7055     }
7056   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7057 }
7058
7059 /*!
7060  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7061  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7062  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7063  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7064  * are not used here to avoid the build of big permutation array.
7065  *
7066  * \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
7067  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7068  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7069  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7070  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7071  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7072  * \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
7073  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7074  */
7075 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7076                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7077                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
7078 {
7079   std::vector<const MEDCouplingUMesh *> ms2;
7080   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7081     if(*it)
7082       {
7083         (*it)->checkConnectivityFullyDefined();
7084         ms2.push_back(*it);
7085       }
7086   if(ms2.empty())
7087     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7088   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7089   int meshDim=ms2[0]->getMeshDimension();
7090   std::vector<const MEDCouplingUMesh *> m1ssm;
7091   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7092   //
7093   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7094   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7095   int fake=0,rk=0;
7096   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7097   ret1->alloc(0,1); ret2->alloc(0,1);
7098   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7099     {
7100       if(meshDim!=(*it)->getMeshDimension())
7101         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7102       if(refCoo!=(*it)->getCoords())
7103         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7104       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7105       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7106       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7107       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7108         {
7109           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7110           m1ssmSingleAuto.push_back(singleCell);
7111           m1ssmSingle.push_back(singleCell);
7112           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7113         }
7114     }
7115   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7116   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7117   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7118   for(std::size_t i=0;i<m1ssm.size();i++)
7119     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7120   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7121   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7122   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7123   return ret0.retn();
7124 }
7125
7126 /*!
7127  * This method returns a newly created DataArrayInt instance.
7128  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7129  */
7130 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7131 {
7132   checkFullyDefined();
7133   const int *conn=_nodal_connec->getConstPointer();
7134   const int *connIndex=_nodal_connec_index->getConstPointer();
7135   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7136   for(const int *w=begin;w!=end;w++)
7137     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7138       ret->pushBackSilent(*w);
7139   return ret.retn();
7140 }
7141
7142 /*!
7143  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7144  * are in [0:getNumberOfCells())
7145  */
7146 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7147 {
7148   checkFullyDefined();
7149   const int *conn=_nodal_connec->getConstPointer();
7150   const int *connI=_nodal_connec_index->getConstPointer();
7151   int nbOfCells=getNumberOfCells();
7152   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7153   int *tmp=new int[nbOfCells];
7154   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7155     {
7156       int j=0;
7157       for(const int *i=connI;i!=connI+nbOfCells;i++)
7158         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7159           tmp[std::distance(connI,i)]=j++;
7160     }
7161   DataArrayInt *ret=DataArrayInt::New();
7162   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7163   ret->copyStringInfoFrom(*da);
7164   int *retPtr=ret->getPointer();
7165   const int *daPtr=da->getConstPointer();
7166   int nbOfElems=da->getNbOfElems();
7167   for(int k=0;k<nbOfElems;k++)
7168     retPtr[k]=tmp[daPtr[k]];
7169   delete [] tmp;
7170   return ret;
7171 }
7172
7173 /*!
7174  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7175  * This method \b works \b for mesh sorted by type.
7176  * cells whose ids is in 'idsPerGeoType' array.
7177  * This method conserves coords and name of mesh.
7178  */
7179 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7180 {
7181   std::vector<int> code=getDistributionOfTypes();
7182   std::size_t nOfTypesInThis=code.size()/3;
7183   int sz=0,szOfType=0;
7184   for(std::size_t i=0;i<nOfTypesInThis;i++)
7185     {
7186       if(code[3*i]!=type)
7187         sz+=code[3*i+1];
7188       else
7189         szOfType=code[3*i+1];
7190     }
7191   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7192     if(*work<0 || *work>=szOfType)
7193       {
7194         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7195         oss << ". It should be in [0," << szOfType << ") !";
7196         throw INTERP_KERNEL::Exception(oss.str().c_str());
7197       }
7198   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7199   int *idsPtr=idsTokeep->getPointer();
7200   int offset=0;
7201   for(std::size_t i=0;i<nOfTypesInThis;i++)
7202     {
7203       if(code[3*i]!=type)
7204         for(int j=0;j<code[3*i+1];j++)
7205           *idsPtr++=offset+j;
7206       else
7207         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7208       offset+=code[3*i+1];
7209     }
7210   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7211   ret->copyTinyInfoFrom(this);
7212   return ret.retn();
7213 }
7214
7215 /*!
7216  * This method returns a vector of size 'this->getNumberOfCells()'.
7217  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7218  */
7219 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7220 {
7221   int ncell=getNumberOfCells();
7222   std::vector<bool> ret(ncell);
7223   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7224   const int *c=getNodalConnectivity()->getConstPointer();
7225   for(int i=0;i<ncell;i++)
7226     {
7227       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7228       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7229       ret[i]=cm.isQuadratic();
7230     }
7231   return ret;
7232 }
7233
7234 /*!
7235  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7236  */
7237 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7238 {
7239   if(other->getType()!=UNSTRUCTURED)
7240     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7241   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7242   return MergeUMeshes(this,otherC);
7243 }
7244
7245 /*!
7246  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7247  * computed by averaging coordinates of cell nodes, so this method is not a right
7248  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7249  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7250  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7251  *          components. The caller is to delete this array using decrRef() as it is
7252  *          no more needed.
7253  *  \throw If the coordinates array is not set.
7254  *  \throw If the nodal connectivity of cells is not defined.
7255  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7256  */
7257 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7258 {
7259   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7260   int spaceDim=getSpaceDimension();
7261   int nbOfCells=getNumberOfCells();
7262   ret->alloc(nbOfCells,spaceDim);
7263   ret->copyStringInfoFrom(*getCoords());
7264   double *ptToFill=ret->getPointer();
7265   const int *nodal=_nodal_connec->getConstPointer();
7266   const int *nodalI=_nodal_connec_index->getConstPointer();
7267   const double *coor=_coords->getConstPointer();
7268   for(int i=0;i<nbOfCells;i++)
7269     {
7270       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7271       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7272       ptToFill+=spaceDim;
7273     }
7274   return ret.retn();
7275 }
7276
7277 /*!
7278  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7279  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7280  * 
7281  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7282  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7283  * 
7284  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7285  * \throw If \a this is not fully defined (coordinates and connectivity)
7286  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7287  */
7288 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7289 {
7290   checkFullyDefined();
7291   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7292   int spaceDim=getSpaceDimension();
7293   int nbOfCells=getNumberOfCells();
7294   int nbOfNodes=getNumberOfNodes();
7295   ret->alloc(nbOfCells,spaceDim);
7296   double *ptToFill=ret->getPointer();
7297   const int *nodal=_nodal_connec->getConstPointer();
7298   const int *nodalI=_nodal_connec_index->getConstPointer();
7299   const double *coor=_coords->getConstPointer();
7300   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7301     {
7302       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7303       std::fill(ptToFill,ptToFill+spaceDim,0.);
7304       if(type!=INTERP_KERNEL::NORM_POLYHED)
7305         {
7306           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7307             {
7308               if(*conn>=0 && *conn<nbOfNodes)
7309                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7310               else
7311                 {
7312                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7313                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7314                 }
7315             }
7316           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7317           if(nbOfNodesInCell>0)
7318             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7319           else
7320             {
7321               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7322               throw INTERP_KERNEL::Exception(oss.str().c_str());
7323             }
7324         }
7325       else
7326         {
7327           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7328           s.erase(-1);
7329           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7330             {
7331               if(*it>=0 && *it<nbOfNodes)
7332                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7333               else
7334                 {
7335                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7336                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7337                 }
7338             }
7339           if(!s.empty())
7340             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7341           else
7342             {
7343               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7344               throw INTERP_KERNEL::Exception(oss.str().c_str());
7345             }
7346         }
7347     }
7348   return ret.retn();
7349 }
7350
7351 /*!
7352  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7353  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7354  * are specified via an array of cell ids. 
7355  *  \warning Validity of the specified cell ids is not checked! 
7356  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7357  *  \param [in] begin - an array of cell ids of interest.
7358  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7359  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7360  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7361  *          caller is to delete this array using decrRef() as it is no more needed. 
7362  *  \throw If the coordinates array is not set.
7363  *  \throw If the nodal connectivity of cells is not defined.
7364  *
7365  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7366  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7367  */
7368 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7369 {
7370   DataArrayDouble *ret=DataArrayDouble::New();
7371   int spaceDim=getSpaceDimension();
7372   int nbOfTuple=(int)std::distance(begin,end);
7373   ret->alloc(nbOfTuple,spaceDim);
7374   double *ptToFill=ret->getPointer();
7375   double *tmp=new double[spaceDim];
7376   const int *nodal=_nodal_connec->getConstPointer();
7377   const int *nodalI=_nodal_connec_index->getConstPointer();
7378   const double *coor=_coords->getConstPointer();
7379   for(const int *w=begin;w!=end;w++)
7380     {
7381       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7382       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7383       ptToFill+=spaceDim;
7384     }
7385   delete [] tmp;
7386   return ret;
7387 }
7388
7389 /*!
7390  * Returns a DataArrayDouble instance giving for each cell in \a this the equation of plane given by "a*X+b*Y+c*Z+d=0".
7391  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7392  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7393  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7394  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7395  * 
7396  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7397  * \throw If spaceDim!=3 or meshDim!=2.
7398  * \throw If connectivity of \a this is invalid.
7399  * \throw If connectivity of a cell in \a this points to an invalid node.
7400  */
7401 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7402 {
7403   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7404   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7405   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7406     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7407   ret->alloc(nbOfCells,4);
7408   double *retPtr(ret->getPointer());
7409   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7410   const double *coor(_coords->begin());
7411   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7412     {
7413       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7414       if(nodalI[1]-nodalI[0]>=3)
7415         {
7416           for(int j=0;j<3;j++)
7417             {
7418               int nodeId(nodal[nodalI[0]+1+j]);
7419               if(nodeId>=0 && nodeId<nbOfNodes)
7420                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7421               else
7422                 {
7423                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7424                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7425                 }
7426             }
7427         }
7428       else
7429         {
7430           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7431           throw INTERP_KERNEL::Exception(oss.str().c_str());
7432         }
7433       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7434       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7435     }
7436   return ret.retn();
7437 }
7438
7439 /*!
7440  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7441  * 
7442  */
7443 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7444 {
7445   if(!da)
7446     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7447   da->checkAllocated();
7448   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7449   ret->setCoords(da);
7450   int nbOfTuples=da->getNumberOfTuples();
7451   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7452   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7453   c->alloc(2*nbOfTuples,1);
7454   cI->alloc(nbOfTuples+1,1);
7455   int *cp=c->getPointer();
7456   int *cip=cI->getPointer();
7457   *cip++=0;
7458   for(int i=0;i<nbOfTuples;i++)
7459     {
7460       *cp++=INTERP_KERNEL::NORM_POINT1;
7461       *cp++=i;
7462       *cip++=2*(i+1);
7463     }
7464   ret->setConnectivity(c,cI,true);
7465   return ret.retn();
7466 }
7467 /*!
7468  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7469  * Cells and nodes of
7470  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7471  *  \param [in] mesh1 - the first mesh.
7472  *  \param [in] mesh2 - the second mesh.
7473  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7474  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7475  *          is no more needed.
7476  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7477  *  \throw If the coordinates array is not set in none of the meshes.
7478  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7479  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7480  */
7481 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7482 {
7483   std::vector<const MEDCouplingUMesh *> tmp(2);
7484   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7485   return MergeUMeshes(tmp);
7486 }
7487
7488 /*!
7489  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7490  * Cells and nodes of
7491  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7492  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7493  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7494  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7495  *          is no more needed.
7496  *  \throw If \a a.size() == 0.
7497  *  \throw If \a a[ *i* ] == NULL.
7498  *  \throw If the coordinates array is not set in none of the meshes.
7499  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7500  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7501 */
7502 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7503 {
7504   std::size_t sz=a.size();
7505   if(sz==0)
7506     return MergeUMeshesLL(a);
7507   for(std::size_t ii=0;ii<sz;ii++)
7508     if(!a[ii])
7509       {
7510         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7511         throw INTERP_KERNEL::Exception(oss.str().c_str());
7512       }
7513   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7514   std::vector< const MEDCouplingUMesh * > aa(sz);
7515   int spaceDim=-3;
7516   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7517     {
7518       const MEDCouplingUMesh *cur=a[i];
7519       const DataArrayDouble *coo=cur->getCoords();
7520       if(coo)
7521         spaceDim=coo->getNumberOfComponents();
7522     }
7523   if(spaceDim==-3)
7524     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7525   for(std::size_t i=0;i<sz;i++)
7526     {
7527       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7528       aa[i]=bb[i];
7529     }
7530   return MergeUMeshesLL(aa);
7531 }
7532
7533 /// @cond INTERNAL
7534
7535 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7536 {
7537   if(a.empty())
7538     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7539   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7540   int meshDim=(*it)->getMeshDimension();
7541   int nbOfCells=(*it)->getNumberOfCells();
7542   int meshLgth=(*it++)->getMeshLength();
7543   for(;it!=a.end();it++)
7544     {
7545       if(meshDim!=(*it)->getMeshDimension())
7546         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7547       nbOfCells+=(*it)->getNumberOfCells();
7548       meshLgth+=(*it)->getMeshLength();
7549     }
7550   std::vector<const MEDCouplingPointSet *> aps(a.size());
7551   std::copy(a.begin(),a.end(),aps.begin());
7552   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7553   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7554   ret->setCoords(pts);
7555   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7556   c->alloc(meshLgth,1);
7557   int *cPtr=c->getPointer();
7558   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7559   cI->alloc(nbOfCells+1,1);
7560   int *cIPtr=cI->getPointer();
7561   *cIPtr++=0;
7562   int offset=0;
7563   int offset2=0;
7564   for(it=a.begin();it!=a.end();it++)
7565     {
7566       int curNbOfCell=(*it)->getNumberOfCells();
7567       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7568       const int *curC=(*it)->_nodal_connec->getConstPointer();
7569       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7570       for(int j=0;j<curNbOfCell;j++)
7571         {
7572           const int *src=curC+curCI[j];
7573           *cPtr++=*src++;
7574           for(;src!=curC+curCI[j+1];src++,cPtr++)
7575             {
7576               if(*src!=-1)
7577                 *cPtr=*src+offset2;
7578               else
7579                 *cPtr=-1;
7580             }
7581         }
7582       offset+=curCI[curNbOfCell];
7583       offset2+=(*it)->getNumberOfNodes();
7584     }
7585   //
7586   ret->setConnectivity(c,cI,true);
7587   return ret.retn();
7588 }
7589
7590 /// @endcond
7591
7592 /*!
7593  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7594  * dimension and sharing the node coordinates array.
7595  * All cells of the first mesh precede all cells of the second mesh
7596  * within the result mesh. 
7597  *  \param [in] mesh1 - the first mesh.
7598  *  \param [in] mesh2 - the second mesh.
7599  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7600  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7601  *          is no more needed.
7602  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7603  *  \throw If the meshes do not share the node coordinates array.
7604  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7605  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7606  */
7607 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7608 {
7609   std::vector<const MEDCouplingUMesh *> tmp(2);
7610   tmp[0]=mesh1; tmp[1]=mesh2;
7611   return MergeUMeshesOnSameCoords(tmp);
7612 }
7613
7614 /*!
7615  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7616  * dimension and sharing the node coordinates array.
7617  * All cells of the *i*-th mesh precede all cells of the
7618  * (*i*+1)-th mesh within the result mesh.
7619  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7620  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7621  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7622  *          is no more needed.
7623  *  \throw If \a a.size() == 0.
7624  *  \throw If \a a[ *i* ] == NULL.
7625  *  \throw If the meshes do not share the node coordinates array.
7626  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7627  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7628  */
7629 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7630 {
7631   if(meshes.empty())
7632     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7633   for(std::size_t ii=0;ii<meshes.size();ii++)
7634     if(!meshes[ii])
7635       {
7636         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7637         throw INTERP_KERNEL::Exception(oss.str().c_str());
7638       }
7639   const DataArrayDouble *coords=meshes.front()->getCoords();
7640   int meshDim=meshes.front()->getMeshDimension();
7641   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7642   int meshLgth=0;
7643   int meshIndexLgth=0;
7644   for(;iter!=meshes.end();iter++)
7645     {
7646       if(coords!=(*iter)->getCoords())
7647         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7648       if(meshDim!=(*iter)->getMeshDimension())
7649         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7650       meshLgth+=(*iter)->getMeshLength();
7651       meshIndexLgth+=(*iter)->getNumberOfCells();
7652     }
7653   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7654   nodal->alloc(meshLgth,1);
7655   int *nodalPtr=nodal->getPointer();
7656   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7657   nodalIndex->alloc(meshIndexLgth+1,1);
7658   int *nodalIndexPtr=nodalIndex->getPointer();
7659   int offset=0;
7660   for(iter=meshes.begin();iter!=meshes.end();iter++)
7661     {
7662       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7663       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7664       int nbOfCells=(*iter)->getNumberOfCells();
7665       int meshLgth2=(*iter)->getMeshLength();
7666       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7667       if(iter!=meshes.begin())
7668         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7669       else
7670         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7671       offset+=meshLgth2;
7672     }
7673   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7674   ret->setName("merge");
7675   ret->setMeshDimension(meshDim);
7676   ret->setConnectivity(nodal,nodalIndex,true);
7677   ret->setCoords(coords);
7678   return ret;
7679 }
7680
7681 /*!
7682  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7683  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7684  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7685  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7686  * New" mode are returned for each input mesh.
7687  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7688  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7689  *          valid values [0,1,2], see zipConnectivityTraducer().
7690  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7691  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7692  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7693  *          no more needed.
7694  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7695  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7696  *          is no more needed.
7697  *  \throw If \a meshes.size() == 0.
7698  *  \throw If \a meshes[ *i* ] == NULL.
7699  *  \throw If the meshes do not share the node coordinates array.
7700  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7701  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7702  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7703  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7704  */
7705 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7706 {
7707   //All checks are delegated to MergeUMeshesOnSameCoords
7708   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7709   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7710   corr.resize(meshes.size());
7711   std::size_t nbOfMeshes=meshes.size();
7712   int offset=0;
7713   const int *o2nPtr=o2n->getConstPointer();
7714   for(std::size_t i=0;i<nbOfMeshes;i++)
7715     {
7716       DataArrayInt *tmp=DataArrayInt::New();
7717       int curNbOfCells=meshes[i]->getNumberOfCells();
7718       tmp->alloc(curNbOfCells,1);
7719       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7720       offset+=curNbOfCells;
7721       tmp->setName(meshes[i]->getName());
7722       corr[i]=tmp;
7723     }
7724   return ret.retn();
7725 }
7726
7727 /*!
7728  * Makes all given meshes share the nodal connectivity array. The common connectivity
7729  * array is created by concatenating the connectivity arrays of all given meshes. All
7730  * the given meshes must be of the same space dimension but dimension of cells **can
7731  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7732  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7733  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7734  *  \param [in,out] meshes - a vector of meshes to update.
7735  *  \throw If any of \a meshes is NULL.
7736  *  \throw If the coordinates array is not set in any of \a meshes.
7737  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7738  *  \throw If \a meshes are of different space dimension.
7739  */
7740 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7741 {
7742   std::size_t sz=meshes.size();
7743   if(sz==0 || sz==1)
7744     return;
7745   std::vector< const DataArrayDouble * > coords(meshes.size());
7746   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7747   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7748     {
7749       if((*it))
7750         {
7751           (*it)->checkConnectivityFullyDefined();
7752           const DataArrayDouble *coo=(*it)->getCoords();
7753           if(coo)
7754             *it2=coo;
7755           else
7756             {
7757               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7758               oss << " has no coordinate array defined !";
7759               throw INTERP_KERNEL::Exception(oss.str().c_str());
7760             }
7761         }
7762       else
7763         {
7764           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7765           oss << " is null !";
7766           throw INTERP_KERNEL::Exception(oss.str().c_str());
7767         }
7768     }
7769   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7770   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7771   int offset=(*it)->getNumberOfNodes();
7772   (*it++)->setCoords(res);
7773   for(;it!=meshes.end();it++)
7774     {
7775       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7776       (*it)->setCoords(res);
7777       (*it)->shiftNodeNumbersInConn(offset);
7778       offset+=oldNumberOfNodes;
7779     }
7780 }
7781
7782 /*!
7783  * Merges nodes coincident with a given precision within all given meshes that share
7784  * the nodal connectivity array. The given meshes **can be of different** mesh
7785  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7786  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7787  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7788  *  \param [in,out] meshes - a vector of meshes to update.
7789  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7790  *  \throw If any of \a meshes is NULL.
7791  *  \throw If the \a meshes do not share the same node coordinates array.
7792  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7793  */
7794 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7795 {
7796   if(meshes.empty())
7797     return ;
7798   std::set<const DataArrayDouble *> s;
7799   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7800     {
7801       if(*it)
7802         s.insert((*it)->getCoords());
7803       else
7804         {
7805           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 !";
7806           throw INTERP_KERNEL::Exception(oss.str().c_str());
7807         }
7808     }
7809   if(s.size()!=1)
7810     {
7811       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 !";
7812       throw INTERP_KERNEL::Exception(oss.str().c_str());
7813     }
7814   const DataArrayDouble *coo=*(s.begin());
7815   if(!coo)
7816     return;
7817   //
7818   DataArrayInt *comm,*commI;
7819   coo->findCommonTuples(eps,-1,comm,commI);
7820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7821   int oldNbOfNodes=coo->getNumberOfTuples();
7822   int newNbOfNodes;
7823   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7824   if(oldNbOfNodes==newNbOfNodes)
7825     return ;
7826   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7827   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7828     {
7829       (*it)->renumberNodesInConn(o2n->getConstPointer());
7830       (*it)->setCoords(newCoords);
7831     } 
7832 }
7833
7834 /*!
7835  * 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.
7836  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7837  * \param isQuad specifies the policy of connectivity.
7838  * @ret in/out parameter in which the result will be append
7839  */
7840 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7841 {
7842   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7843   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7844   ret.push_back(cm.getExtrudedType());
7845   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7846   switch(flatType)
7847     {
7848     case INTERP_KERNEL::NORM_POINT1:
7849       {
7850         ret.push_back(connBg[1]);
7851         ret.push_back(connBg[1]+nbOfNodesPerLev);
7852         break;
7853       }
7854     case INTERP_KERNEL::NORM_SEG2:
7855       {
7856         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7857         ret.insert(ret.end(),conn,conn+4);
7858         break;
7859       }
7860     case INTERP_KERNEL::NORM_SEG3:
7861       {
7862         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7863         ret.insert(ret.end(),conn,conn+8);
7864         break;
7865       }
7866     case INTERP_KERNEL::NORM_QUAD4:
7867       {
7868         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7869         ret.insert(ret.end(),conn,conn+8);
7870         break;
7871       }
7872     case INTERP_KERNEL::NORM_TRI3:
7873       {
7874         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7875         ret.insert(ret.end(),conn,conn+6);
7876         break;
7877       }
7878     case INTERP_KERNEL::NORM_TRI6:
7879       {
7880         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,
7881                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7882         ret.insert(ret.end(),conn,conn+15);
7883         break;
7884       }
7885     case INTERP_KERNEL::NORM_QUAD8:
7886       {
7887         int conn[20]={
7888           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7889           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7890           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7891         };
7892         ret.insert(ret.end(),conn,conn+20);
7893         break;
7894       }
7895     case INTERP_KERNEL::NORM_POLYGON:
7896       {
7897         std::back_insert_iterator< std::vector<int> > ii(ret);
7898         std::copy(connBg+1,connEnd,ii);
7899         *ii++=-1;
7900         std::reverse_iterator<const int *> rConnBg(connEnd);
7901         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7902         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7903         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7904         for(std::size_t i=0;i<nbOfRadFaces;i++)
7905           {
7906             *ii++=-1;
7907             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7908             std::copy(conn,conn+4,ii);
7909           }
7910         break;
7911       }
7912     default:
7913       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7914     }
7915 }
7916
7917 /*!
7918  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7919  */
7920 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7921 {
7922   std::size_t i, ip1;
7923   double v[3]={0.,0.,0.};
7924   std::size_t sz=std::distance(begin,end);
7925   if(isQuadratic)
7926     sz/=2;
7927   for(i=0;i<sz;i++)
7928     {
7929       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];
7930       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7931       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7932     }
7933   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
7934
7935   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
7936   // SEG3 forming a circle):
7937   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
7938     {
7939       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
7940       for(std::size_t j=0;j<sz;j++)
7941         {
7942           if (j%2)  // current point i is quadratic, next point i+1 is standard
7943             {
7944               i = sz+j;
7945               ip1 = (j+1)%sz; // ip1 = "i+1"
7946             }
7947           else      // current point i is standard, next point i+1 is quadratic
7948             {
7949               i = j;
7950               ip1 = j+sz;
7951             }
7952           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
7953           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
7954           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
7955         }
7956       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
7957     }
7958   return (ret>0.);
7959 }
7960
7961 /*!
7962  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7963  */
7964 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7965 {
7966   std::vector<std::pair<int,int> > edges;
7967   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7968   const int *bgFace=begin;
7969   for(std::size_t i=0;i<nbOfFaces;i++)
7970     {
7971       const int *endFace=std::find(bgFace+1,end,-1);
7972       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7973       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7974         {
7975           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7976           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7977             return false;
7978           edges.push_back(p1);
7979         }
7980       bgFace=endFace+1;
7981     }
7982   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7983 }
7984
7985 /*!
7986  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7987  */
7988 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7989 {
7990   double vec0[3],vec1[3];
7991   std::size_t sz=std::distance(begin,end);
7992   if(sz%2!=0)
7993     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7994   int nbOfNodes=(int)sz/2;
7995   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7996   const double *pt0=coords+3*begin[0];
7997   const double *pt1=coords+3*begin[nbOfNodes];
7998   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7999   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8000 }
8001
8002 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8003 {
8004   std::size_t sz=std::distance(begin,end);
8005   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8006   std::size_t nbOfNodes(sz/2);
8007   std::copy(begin,end,(int *)tmp);
8008   for(std::size_t j=1;j<nbOfNodes;j++)
8009     {
8010       begin[j]=tmp[nbOfNodes-j];
8011       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8012     }
8013 }
8014
8015 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8016 {
8017   std::size_t sz=std::distance(begin,end);
8018   if(sz!=4)
8019     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8020   double vec0[3],vec1[3];
8021   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8022   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]; 
8023   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;
8024 }
8025
8026 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8027 {
8028   std::size_t sz=std::distance(begin,end);
8029   if(sz!=5)
8030     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8031   double vec0[3];
8032   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8033   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8034   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8035 }
8036
8037 /*!
8038  * 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 ) 
8039  * 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
8040  * a 2D space.
8041  *
8042  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8043  * \param [in] coords the coordinates with nb of components exactly equal to 3
8044  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8045  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8046  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8047  */
8048 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8049 {
8050   int nbFaces=std::count(begin+1,end,-1)+1;
8051   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8052   double *vPtr=v->getPointer();
8053   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8054   double *pPtr=p->getPointer();
8055   const int *stFaceConn=begin+1;
8056   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8057     {
8058       const int *endFaceConn=std::find(stFaceConn,end,-1);
8059       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8060       stFaceConn=endFaceConn+1;
8061     }
8062   pPtr=p->getPointer(); vPtr=v->getPointer();
8063   DataArrayInt *comm1=0,*commI1=0;
8064   v->findCommonTuples(eps,-1,comm1,commI1);
8065   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8066   const int *comm1Ptr=comm1->getConstPointer();
8067   const int *commI1Ptr=commI1->getConstPointer();
8068   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8069   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8070   //
8071   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8072   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8073   mm->finishInsertingCells();
8074   //
8075   for(int i=0;i<nbOfGrps1;i++)
8076     {
8077       int vecId=comm1Ptr[commI1Ptr[i]];
8078       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8079       DataArrayInt *comm2=0,*commI2=0;
8080       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8081       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8082       const int *comm2Ptr=comm2->getConstPointer();
8083       const int *commI2Ptr=commI2->getConstPointer();
8084       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8085       for(int j=0;j<nbOfGrps2;j++)
8086         {
8087           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8088             {
8089               res->insertAtTheEnd(begin,end);
8090               res->pushBackSilent(-1);
8091             }
8092           else
8093             {
8094               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8095               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8096               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8097               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8098               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8099               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8100               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8101               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8102               const int *idsNodePtr=idsNode->getConstPointer();
8103               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];
8104               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8105               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8106               if(std::abs(norm)>eps)
8107                 {
8108                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8109                   mm3->rotate(center,vec,angle);
8110                 }
8111               mm3->changeSpaceDimension(2);
8112               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8113               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8114               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8115               int nbOfCells=mm4->getNumberOfCells();
8116               for(int k=0;k<nbOfCells;k++)
8117                 {
8118                   int l=0;
8119                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8120                     res->pushBackSilent(idsNodePtr[*work]);
8121                   res->pushBackSilent(-1);
8122                 }
8123             }
8124         }
8125     }
8126   res->popBackSilent();
8127 }
8128
8129 /*!
8130  * 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
8131  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8132  * 
8133  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8134  * \param [in] coords coordinates expected to have 3 components.
8135  * \param [in] begin start of the nodal connectivity of the face.
8136  * \param [in] end end of the nodal connectivity (excluded) of the face.
8137  * \param [out] v the normalized vector of size 3
8138  * \param [out] p the pos of plane
8139  */
8140 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8141 {
8142   std::size_t nbPoints=std::distance(begin,end);
8143   if(nbPoints<3)
8144     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8145   double vec[3]={0.,0.,0.};
8146   std::size_t j=0;
8147   bool refFound=false;
8148   for(;j<nbPoints-1 && !refFound;j++)
8149     {
8150       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8151       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8152       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8153       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8154       if(norm>eps)
8155         {
8156           refFound=true;
8157           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8158         }
8159     }
8160   for(std::size_t i=j;i<nbPoints-1;i++)
8161     {
8162       double curVec[3];
8163       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8164       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8165       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8166       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8167       if(norm<eps)
8168         continue;
8169       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8170       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];
8171       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8172       if(norm>eps)
8173         {
8174           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8175           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8176           return ;
8177         }
8178     }
8179   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8180 }
8181
8182 /*!
8183  * This method tries to obtain a well oriented polyhedron.
8184  * If the algorithm fails, an exception will be thrown.
8185  */
8186 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8187 {
8188   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8189   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8190   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8191   isPerm[0]=true;
8192   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8193   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8194   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8195   //
8196   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8197     {
8198       bgFace=begin;
8199       std::size_t smthChanged=0;
8200       for(std::size_t i=0;i<nbOfFaces;i++)
8201         {
8202           endFace=std::find(bgFace+1,end,-1);
8203           nbOfEdgesInFace=std::distance(bgFace,endFace);
8204           if(!isPerm[i])
8205             {
8206               bool b;
8207               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8208                 {
8209                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8210                   std::pair<int,int> p2(p1.second,p1.first);
8211                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8212                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8213                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8214                 }
8215               if(isPerm[i])
8216                 { 
8217                   if(!b)
8218                     std::reverse(bgFace+1,endFace);
8219                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8220                     {
8221                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8222                       std::pair<int,int> p2(p1.second,p1.first);
8223                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8224                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8225                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8226                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8227                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8228                       if(it!=edgesOK.end())
8229                         {
8230                           edgesOK.erase(it);
8231                           edgesFinished.push_back(p1);
8232                         }
8233                       else
8234                         edgesOK.push_back(p1);
8235                     }
8236                 }
8237             }
8238           bgFace=endFace+1;
8239         }
8240       if(smthChanged==0)
8241         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8242     }
8243   if(!edgesOK.empty())
8244     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8245   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8246     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8247       bgFace=begin;
8248       for(std::size_t i=0;i<nbOfFaces;i++)
8249         {
8250           endFace=std::find(bgFace+1,end,-1);
8251           std::reverse(bgFace+1,endFace);
8252           bgFace=endFace+1;
8253         }
8254     }
8255 }
8256
8257 /*!
8258  * This method makes the assumption spacedimension == meshdimension == 2.
8259  * This method works only for linear cells.
8260  * 
8261  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8262  */
8263 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8264 {
8265   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8266     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8267   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8268   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
8269   int nbOfNodesExpected=m->getNumberOfNodes();
8270   if(m->getNumberOfCells()!=nbOfNodesExpected)
8271     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
8272   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
8273   const int *n2oPtr=n2o->getConstPointer();
8274   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8275   m->getReverseNodalConnectivity(revNodal,revNodalI);
8276   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
8277   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
8278   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
8279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
8280   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
8281   if(nbOfNodesExpected<1)
8282     return ret.retn();
8283   int prevCell=0;
8284   int prevNode=nodalPtr[nodalIPtr[0]+1];
8285   *work++=n2oPtr[prevNode];
8286   for(int i=1;i<nbOfNodesExpected;i++)
8287     {
8288       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8289         {
8290           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8291           conn.erase(prevNode);
8292           if(conn.size()==1)
8293             {
8294               int curNode=*(conn.begin());
8295               *work++=n2oPtr[curNode];
8296               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8297               shar.erase(prevCell);
8298               if(shar.size()==1)
8299                 {
8300                   prevCell=*(shar.begin());
8301                   prevNode=curNode;
8302                 }
8303               else
8304                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8305             }
8306           else
8307             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8308         }
8309       else
8310         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8311     }
8312   return ret.retn();
8313 }
8314
8315 /*!
8316  * This method makes the assumption spacedimension == meshdimension == 3.
8317  * This method works only for linear cells.
8318  * 
8319  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8320  */
8321 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8322 {
8323   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8324     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8325   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8326   const int *conn=m->getNodalConnectivity()->getConstPointer();
8327   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8328   int nbOfCells=m->getNumberOfCells();
8329   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8330   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8331   if(nbOfCells<1)
8332     return ret.retn();
8333   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8334   for(int i=1;i<nbOfCells;i++)
8335     {
8336       *work++=-1;
8337       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8338     }
8339   return ret.retn();
8340 }
8341
8342 /*!
8343  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8344  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8345  */
8346 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8347 {
8348   double *w=zipFrmt;
8349   if(spaceDim==3)
8350     for(int i=0;i<nbOfNodesInCell;i++)
8351       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8352   else if(spaceDim==2)
8353     {
8354       for(int i=0;i<nbOfNodesInCell;i++)
8355         {
8356           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8357           *w++=0.;
8358         }
8359     }
8360   else
8361     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8362 }
8363
8364 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8365 {
8366   int nbOfCells=getNumberOfCells();
8367   if(nbOfCells<=0)
8368     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8369   static const int PARAMEDMEM2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,34,23,28,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,29,-1,-1,25,42,36,4};
8370   ofs << "  <" << getVTKDataSetType() << ">\n";
8371   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8372   ofs << "      <PointData>\n" << pointData << std::endl;
8373   ofs << "      </PointData>\n";
8374   ofs << "      <CellData>\n" << cellData << std::endl;
8375   ofs << "      </CellData>\n";
8376   ofs << "      <Points>\n";
8377   if(getSpaceDimension()==3)
8378     _coords->writeVTK(ofs,8,"Points",byteData);
8379   else
8380     {
8381       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8382       coo->writeVTK(ofs,8,"Points",byteData);
8383     }
8384   ofs << "      </Points>\n";
8385   ofs << "      <Cells>\n";
8386   const int *cPtr=_nodal_connec->getConstPointer();
8387   const int *cIPtr=_nodal_connec_index->getConstPointer();
8388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8389   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8392   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8393   int szFaceOffsets=0,szConn=0;
8394   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8395     {
8396       *w2=cPtr[cIPtr[i]];
8397       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8398         {
8399           *w1=-1;
8400           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8401           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8402         }
8403       else
8404         {
8405           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8406           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8407           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8408           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8409           w4=std::copy(c.begin(),c.end(),w4);
8410         }
8411     }
8412   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8413   types->writeVTK(ofs,8,"UInt8","types",byteData);
8414   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8415   if(szFaceOffsets!=0)
8416     {//presence of Polyhedra
8417       connectivity->reAlloc(szConn);
8418       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8419       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8420       w1=faces->getPointer();
8421       for(int i=0;i<nbOfCells;i++)
8422         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8423           {
8424             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8425             *w1++=nbFaces;
8426             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8427             for(int j=0;j<nbFaces;j++)
8428               {
8429                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8430                 *w1++=(int)std::distance(w6,w5);
8431                 w1=std::copy(w6,w5,w1);
8432                 w6=w5+1;
8433               }
8434           }
8435       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8436     }
8437   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8438   ofs << "      </Cells>\n";
8439   ofs << "    </Piece>\n";
8440   ofs << "  </" << getVTKDataSetType() << ">\n";
8441 }
8442
8443 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8444 {
8445   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8446   if(_mesh_dim==-2)
8447     { stream << " Not set !"; return ; }
8448   stream << " Mesh dimension : " << _mesh_dim << ".";
8449   if(_mesh_dim==-1)
8450     return ;
8451   if(!_coords)
8452     { stream << " No coordinates set !"; return ; }
8453   if(!_coords->isAllocated())
8454     { stream << " Coordinates set but not allocated !"; return ; }
8455   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8456   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8457   if(!_nodal_connec_index)
8458     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8459   if(!_nodal_connec_index->isAllocated())
8460     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8461   int lgth=_nodal_connec_index->getNumberOfTuples();
8462   int cpt=_nodal_connec_index->getNumberOfComponents();
8463   if(cpt!=1 || lgth<1)
8464     return ;
8465   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8466 }
8467
8468 std::string MEDCouplingUMesh::getVTKDataSetType() const
8469 {
8470   return std::string("UnstructuredGrid");
8471 }
8472
8473 /*!
8474  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8475  * returns a result mesh constituted by polygons.
8476  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8477  * all nodes from m2.
8478  * The meshes should be in 2D space. In
8479  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8480  * meshes.
8481  *  \param [in] m1 - the first input mesh which is a partitioned object.
8482  *  \param [in] m2 - the second input mesh which is a partition tool.
8483  *  \param [in] eps - precision used to detect coincident mesh entities.
8484  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8485  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8486  *         this array using decrRef() as it is no more needed.
8487  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8488  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8489  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8490  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8491  *         it is no more needed.  
8492  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8493  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8494  *         is no more needed.  
8495  *  \throw If the coordinates array is not set in any of the meshes.
8496  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8497  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8498  */
8499 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8500                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8501 {
8502   m1->checkFullyDefined();
8503   m2->checkFullyDefined();
8504   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8505     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8506
8507   // Step 1: compute all edge intersections (new nodes)
8508   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8509   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8510   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8511   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8512   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8513   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8514   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8515                                       m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8516                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8517   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8518   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8519   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8520
8521   // Step 2: re-order newly created nodes according to the ordering found in m2
8522   std::vector< std::vector<int> > intersectEdge2;
8523   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8524   subDiv2.clear(); dd5=0; dd6=0;
8525
8526   // Step 3:
8527   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8528   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8529   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8530                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8531
8532   // Step 4: Prepare final result:
8533   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8534   addCooDa->alloc((int)(addCoo.size())/2,2);
8535   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8536   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8537   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8538   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8539   std::vector<const DataArrayDouble *> coordss(4);
8540   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8541   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8542   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8543   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8544   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8545   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8546   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8547   ret->setConnectivity(conn,connI,true);
8548   ret->setCoords(coo);
8549   cellNb1=c1.retn(); cellNb2=c2.retn();
8550   return ret.retn();
8551 }
8552
8553
8554 /**
8555  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
8556  * (newly created) nodes corresponding to the edge intersections.
8557  * Output params:
8558  * @param[out] cr, crI connectivity of the resulting mesh
8559  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
8560  * TODO: describe input parameters
8561  */
8562 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8563                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8564                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8565                                                          const std::vector<double>& addCoords,
8566                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8567 {
8568   static const int SPACEDIM=2;
8569   const double *coo1=m1->getCoords()->getConstPointer();
8570   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8571   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8572   int offset1=m1->getNumberOfNodes();
8573   const double *coo2=m2->getCoords()->getConstPointer();
8574   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8575   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8576   int offset2=offset1+m2->getNumberOfNodes();
8577   int offset3=offset2+((int)addCoords.size())/2;
8578   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8579   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8580   // Here a BBTree on 2D-cells, not on segments:
8581   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8582   int ncell1=m1->getNumberOfCells();
8583   crI.push_back(0);
8584   for(int i=0;i<ncell1;i++)
8585     {
8586       std::vector<int> candidates2;
8587       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8588       std::map<INTERP_KERNEL::Node *,int> mapp;
8589       std::map<int,INTERP_KERNEL::Node *> mappRev;
8590       INTERP_KERNEL::QuadraticPolygon pol1;
8591       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8592       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8593       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
8594       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8595       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
8596       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8597                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8598       //
8599       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
8600       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8601       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8602       for(it1.first();!it1.finished();it1.next())
8603         edges1.insert(it1.current()->getPtr());
8604       //
8605       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
8606       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8607       int ii=0;
8608       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8609         {
8610           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8611           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8612           // Complete mapping with elements coming from the current cell it2 in mesh2:
8613           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8614           // pol2 is the new QP in the final merged result.
8615           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8616                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
8617         }
8618       ii=0;
8619       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8620         {
8621           pol1.initLocationsWithOther(pol2s[ii]);
8622           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8623           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8624           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8625         }
8626       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
8627       // by m2 but that we still want to keep in the final result.
8628       if(!edges1.empty())
8629         {
8630           try
8631             {
8632               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8633             }
8634           catch(INTERP_KERNEL::Exception& e)
8635             {
8636               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();
8637               throw INTERP_KERNEL::Exception(oss.str().c_str());
8638             }
8639         }
8640       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8641         (*it).second->decrRef();
8642     }
8643 }
8644
8645 /*!
8646  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8647  * It builds the descending connectivity of the two meshes, and then using a binary tree
8648  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
8649  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
8650  */
8651 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8652                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8653                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8654                                                    std::vector<double>& addCoo,
8655                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
8656                                                    throw(INTERP_KERNEL::Exception)
8657 {
8658   static const int SPACEDIM=2;
8659   // Build desc connectivity
8660   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8661   desc2=DataArrayInt::New();
8662   descIndx2=DataArrayInt::New();
8663   revDesc2=DataArrayInt::New();
8664   revDescIndx2=DataArrayInt::New();
8665   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8666   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8667   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8668   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8669   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8670   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8671   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8672
8673   // Build BB tree of all edges in the tool mesh (second mesh)
8674   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
8675   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8676   int nDescCell1=m1Desc->getNumberOfCells();
8677   int nDescCell2=m2Desc->getNumberOfCells();
8678   intersectEdge1.resize(nDescCell1);
8679   colinear2.resize(nDescCell2);
8680   subDiv2.resize(nDescCell2);
8681   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
8682
8683   std::vector<int> candidates1(1);
8684   int offset1=m1->getNumberOfNodes();
8685   int offset2=offset1+m2->getNumberOfNodes();
8686   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
8687     {
8688       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
8689       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8690       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
8691         {
8692           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8693           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
8694           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8695           candidates1[0]=i;
8696           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8697           // This following part is to avoid that some removed nodes (for example due to a merge between pol1 and pol2) are replaced by a newly created one
8698           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
8699           std::set<INTERP_KERNEL::Node *> nodes;
8700           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
8701           std::size_t szz(nodes.size());
8702           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
8703           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
8704           for(std::size_t iii=0;iii<szz;iii++,itt++)
8705             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
8706           // end of protection
8707           // Performs egde cutting:
8708           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8709           delete pol2;
8710           delete pol1;
8711         }
8712       else
8713         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8714     }
8715   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8716   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8717 }
8718
8719 /*!
8720  * This method performs the 2nd step of Partition of 2D mesh.
8721  * This method has 4 inputs :
8722  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8723  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8724  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
8725  * The aim of this method is to sort the splitting nodes, if any, and to put them in 'intersectEdge' output parameter based on edges of mesh 'm2'
8726  * Nodes end up lying consecutively on a cutted edge.
8727  * \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.
8728  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
8729  * \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.
8730  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
8731  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
8732  */
8733 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8734       const std::vector<double>& addCoo,
8735       const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
8736 {
8737   int offset1=m1->getNumberOfNodes();
8738   int ncell=m2->getNumberOfCells();
8739   const int *c=m2->getNodalConnectivity()->getConstPointer();
8740   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8741   const double *coo=m2->getCoords()->getConstPointer();
8742   const double *cooBis=m1->getCoords()->getConstPointer();
8743   int offset2=offset1+m2->getNumberOfNodes();
8744   intersectEdge.resize(ncell);
8745   for(int i=0;i<ncell;i++,cI++)
8746     {
8747       const std::vector<int>& divs=subDiv[i];
8748       int nnode=cI[1]-cI[0]-1;
8749       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8750       std::map<INTERP_KERNEL::Node *, int> mapp22;
8751       for(int j=0;j<nnode;j++)
8752         {
8753           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8754           int nnid=c[(*cI)+j+1];
8755           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8756           mapp22[nn]=nnid+offset1;
8757         }
8758       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8759       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8760         ((*it).second.first)->decrRef();
8761       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8762       std::map<INTERP_KERNEL::Node *,int> mapp3;
8763       for(std::size_t j=0;j<divs.size();j++)
8764         {
8765           int id=divs[j];
8766           INTERP_KERNEL::Node *tmp=0;
8767           if(id<offset1)
8768             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8769           else if(id<offset2)
8770             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8771           else
8772             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8773           addNodes[j]=tmp;
8774           mapp3[tmp]=id;
8775         }
8776       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8777       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8778         (*it)->decrRef();
8779       e->decrRef();
8780     }
8781 }
8782
8783 /*!
8784  * 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).
8785  * 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
8786  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8787  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8788  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8789  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8790  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8791  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8792  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8793  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8794  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8795  * \param [out] cut3DSuf input/output param.
8796  */
8797 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8798                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8799                                                    const int *desc, const int *descIndx, 
8800                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8801 {
8802   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8803   int nbOf3DSurfCell=(int)cut3DSurf.size();
8804   for(int i=0;i<nbOf3DSurfCell;i++)
8805     {
8806       std::vector<int> res;
8807       int offset=descIndx[i];
8808       int nbOfSeg=descIndx[i+1]-offset;
8809       for(int j=0;j<nbOfSeg;j++)
8810         {
8811           int edgeId=desc[offset+j];
8812           int status=cut3DCurve[edgeId];
8813           if(status!=-2)
8814             {
8815               if(status>-1)
8816                 res.push_back(status);
8817               else
8818                 {
8819                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8820                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8821                 }
8822             }
8823         }
8824       switch(res.size())
8825         {
8826         case 2:
8827           {
8828             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8829             break;
8830           }
8831         case 1:
8832         case 0:
8833           {
8834             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8835             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8836             if(res.size()==2)
8837               {
8838                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8839               }
8840             else
8841               {
8842                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8843               }
8844             break;
8845           }
8846         default:
8847           {// case when plane is on a multi colinear edge of a polyhedron
8848             if((int)res.size()==2*nbOfSeg)
8849               {
8850                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8851               }
8852             else
8853               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8854           }
8855         }
8856     }
8857 }
8858
8859 /*!
8860  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8861  * 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).
8862  * 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
8863  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8864  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8865  * \param desc is the descending connectivity 3D->3DSurf
8866  * \param descIndx is the descending connectivity index 3D->3DSurf
8867  */
8868 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8869                                                   const int *desc, const int *descIndx,
8870                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8871 {
8872   checkFullyDefined();
8873   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8874     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8875   const int *nodal3D=_nodal_connec->getConstPointer();
8876   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8877   int nbOfCells=getNumberOfCells();
8878   for(int i=0;i<nbOfCells;i++)
8879     {
8880       std::map<int, std::set<int> > m;
8881       int offset=descIndx[i];
8882       int nbOfFaces=descIndx[i+1]-offset;
8883       int start=-1;
8884       int end=-1;
8885       for(int j=0;j<nbOfFaces;j++)
8886         {
8887           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8888           if(p.first!=-1 && p.second!=-1)
8889             {
8890               if(p.first!=-2)
8891                 {
8892                   start=p.first; end=p.second;
8893                   m[p.first].insert(p.second);
8894                   m[p.second].insert(p.first);
8895                 }
8896               else
8897                 {
8898                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8899                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8900                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8901                   INTERP_KERNEL::NormalizedCellType cmsId;
8902                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8903                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8904                   for(unsigned k=0;k<nbOfNodesSon;k++)
8905                     {
8906                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8907                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8908                     }
8909                 }
8910             }
8911         }
8912       if(m.empty())
8913         continue;
8914       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8915       int prev=end;
8916       while(end!=start)
8917         {
8918           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8919           const std::set<int>& s=(*it).second;
8920           std::set<int> s2; s2.insert(prev);
8921           std::set<int> s3;
8922           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8923           if(s3.size()==1)
8924             {
8925               int val=*s3.begin();
8926               conn.push_back(start);
8927               prev=start;
8928               start=val;
8929             }
8930           else
8931             start=end;
8932         }
8933       conn.push_back(end);
8934       if(conn.size()>3)
8935         {
8936           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8937           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8938           cellIds->pushBackSilent(i);
8939         }
8940     }
8941 }
8942
8943 /*!
8944  * 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
8945  * 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
8946  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8947  * 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
8948  * 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.
8949  * 
8950  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8951  */
8952 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
8953 {
8954   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8955   if(sz>=4)
8956     {
8957       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8958       if(cm.getDimension()==2)
8959         {
8960           const int *node=nodalConnBg+1;
8961           int startNode=*node++;
8962           double refX=coords[2*startNode];
8963           for(;node!=nodalConnEnd;node++)
8964             {
8965               if(coords[2*(*node)]<refX)
8966                 {
8967                   startNode=*node;
8968                   refX=coords[2*startNode];
8969                 }
8970             }
8971           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8972           refX=1e300;
8973           double tmp1;
8974           double tmp2[2];
8975           double angle0=-M_PI/2;
8976           //
8977           int nextNode=-1;
8978           int prevNode=-1;
8979           double resRef;
8980           double angleNext=0.;
8981           while(nextNode!=startNode)
8982             {
8983               nextNode=-1;
8984               resRef=1e300;
8985               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8986                 {
8987                   if(*node!=tmpOut.back() && *node!=prevNode)
8988                     {
8989                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8990                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8991                       double res;
8992                       if(angleM<=angle0)
8993                         res=angle0-angleM;
8994                       else
8995                         res=angle0-angleM+2.*M_PI;
8996                       if(res<resRef)
8997                         {
8998                           nextNode=*node;
8999                           resRef=res;
9000                           angleNext=angleM;
9001                         }
9002                     }
9003                 }
9004               if(nextNode!=startNode)
9005                 {
9006                   angle0=angleNext-M_PI;
9007                   if(angle0<-M_PI)
9008                     angle0+=2*M_PI;
9009                   prevNode=tmpOut.back();
9010                   tmpOut.push_back(nextNode);
9011                 }
9012             }
9013           std::vector<int> tmp3(2*(sz-1));
9014           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
9015           std::copy(nodalConnBg+1,nodalConnEnd,it);
9016           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
9017             {
9018               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9019               return false;
9020             }
9021           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
9022             {
9023               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9024               return false;
9025             }
9026           else
9027             {
9028               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
9029               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
9030               return true;
9031             }
9032         }
9033       else
9034         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9035     }
9036   else
9037     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9038 }
9039
9040 /*!
9041  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
9042  * 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.
9043  * 
9044  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
9045  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
9046  * \param [in,out] arr array in which the remove operation will be done.
9047  * \param [in,out] arrIndx array in the remove operation will modify
9048  * \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])
9049  * \return true if \b arr and \b arrIndx have been modified, false if not.
9050  */
9051 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
9052 {
9053   if(!arrIndx || !arr)
9054     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
9055   if(offsetForRemoval<0)
9056     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
9057   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
9058   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
9059   int *arrIPtr=arrIndx->getPointer();
9060   *arrIPtr++=0;
9061   int previousArrI=0;
9062   const int *arrPtr=arr->getConstPointer();
9063   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
9064   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
9065     {
9066       if(*arrIPtr-previousArrI>offsetForRemoval)
9067         {
9068           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
9069             {
9070               if(s.find(*work)==s.end())
9071                 arrOut.push_back(*work);
9072             }
9073         }
9074       previousArrI=*arrIPtr;
9075       *arrIPtr=(int)arrOut.size();
9076     }
9077   if(arr->getNumberOfTuples()==(int)arrOut.size())
9078     return false;
9079   arr->alloc((int)arrOut.size(),1);
9080   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
9081   return true;
9082 }
9083
9084 /*!
9085  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9086  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
9087  * The selection of extraction is done standardly in new2old format.
9088  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9089  *
9090  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9091  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9092  * \param [in] arrIn arr origin array from which the extraction will be done.
9093  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9094  * \param [out] arrOut the resulting array
9095  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9096  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
9097  */
9098 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9099                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9100 {
9101   if(!arrIn || !arrIndxIn)
9102     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
9103   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9104   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9105     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
9106   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
9107   const int *arrInPtr=arrIn->getConstPointer();
9108   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9109   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9110   if(nbOfGrps<0)
9111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9112   int maxSizeOfArr=arrIn->getNumberOfTuples();
9113   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9114   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9115   arrIo->alloc((int)(sz+1),1);
9116   const int *idsIt=idsOfSelectBg;
9117   int *work=arrIo->getPointer();
9118   *work++=0;
9119   int lgth=0;
9120   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
9121     {
9122       if(*idsIt>=0 && *idsIt<nbOfGrps)
9123         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
9124       else
9125         {
9126           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9127           throw INTERP_KERNEL::Exception(oss.str().c_str());
9128         }
9129       if(lgth>=work[-1])
9130         *work=lgth;
9131       else
9132         {
9133           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
9134           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
9135           throw INTERP_KERNEL::Exception(oss.str().c_str());
9136         }
9137     }
9138   arro->alloc(lgth,1);
9139   work=arro->getPointer();
9140   idsIt=idsOfSelectBg;
9141   for(std::size_t i=0;i<sz;i++,idsIt++)
9142     {
9143       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
9144         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
9145       else
9146         {
9147           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
9148           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9149           throw INTERP_KERNEL::Exception(oss.str().c_str());
9150         }
9151     }
9152   arrOut=arro.retn();
9153   arrIndexOut=arrIo.retn();
9154 }
9155
9156 /*!
9157  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9158  * This method returns the result of the extraction ( specified by a set of ids with a slice given by \a idsOfSelectStart, \a idsOfSelectStop and \a idsOfSelectStep ).
9159  * The selection of extraction is done standardly in new2old format.
9160  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9161  *
9162  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9163  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9164  * \param [in] arrIn arr origin array from which the extraction will be done.
9165  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9166  * \param [out] arrOut the resulting array
9167  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9168  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
9169  */
9170 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9171                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9172 {
9173   if(!arrIn || !arrIndxIn)
9174     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
9175   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9176   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9177     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
9178   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
9179   const int *arrInPtr=arrIn->getConstPointer();
9180   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9181   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9182   if(nbOfGrps<0)
9183     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9184   int maxSizeOfArr=arrIn->getNumberOfTuples();
9185   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9186   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9187   arrIo->alloc((int)(sz+1),1);
9188   int idsIt=idsOfSelectStart;
9189   int *work=arrIo->getPointer();
9190   *work++=0;
9191   int lgth=0;
9192   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
9193     {
9194       if(idsIt>=0 && idsIt<nbOfGrps)
9195         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
9196       else
9197         {
9198           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9199           throw INTERP_KERNEL::Exception(oss.str().c_str());
9200         }
9201       if(lgth>=work[-1])
9202         *work=lgth;
9203       else
9204         {
9205           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
9206           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
9207           throw INTERP_KERNEL::Exception(oss.str().c_str());
9208         }
9209     }
9210   arro->alloc(lgth,1);
9211   work=arro->getPointer();
9212   idsIt=idsOfSelectStart;
9213   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
9214     {
9215       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
9216         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
9217       else
9218         {
9219           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
9220           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9221           throw INTERP_KERNEL::Exception(oss.str().c_str());
9222         }
9223     }
9224   arrOut=arro.retn();
9225   arrIndexOut=arrIo.retn();
9226 }
9227
9228 /*!
9229  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9230  * 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
9231  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9232  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9233  *
9234  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9235  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9236  * \param [in] arrIn arr origin array from which the extraction will be done.
9237  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9238  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
9239  * \param [in] srcArrIndex index array of \b srcArr
9240  * \param [out] arrOut the resulting array
9241  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9242  * 
9243  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9244  */
9245 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9246                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9247                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9248 {
9249   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9250     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9251   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9252   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9253   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9254   std::vector<bool> v(nbOfTuples,true);
9255   int offset=0;
9256   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9257   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9258   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9259     {
9260       if(*it>=0 && *it<nbOfTuples)
9261         {
9262           v[*it]=false;
9263           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9264         }
9265       else
9266         {
9267           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9268           throw INTERP_KERNEL::Exception(oss.str().c_str());
9269         }
9270     }
9271   srcArrIndexPtr=srcArrIndex->getConstPointer();
9272   arrIo->alloc(nbOfTuples+1,1);
9273   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9274   const int *arrInPtr=arrIn->getConstPointer();
9275   const int *srcArrPtr=srcArr->getConstPointer();
9276   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9277   int *arroPtr=arro->getPointer();
9278   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9279     {
9280       if(v[ii])
9281         {
9282           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9283           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9284         }
9285       else
9286         {
9287           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9288           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9289           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9290         }
9291     }
9292   arrOut=arro.retn();
9293   arrIndexOut=arrIo.retn();
9294 }
9295
9296 /*!
9297  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9298  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9299  *
9300  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9301  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9302  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9303  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9304  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
9305  * \param [in] srcArrIndex index array of \b srcArr
9306  * 
9307  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9308  */
9309 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9310                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9311 {
9312   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9313     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9314   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9315   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9316   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9317   int *arrInOutPtr=arrInOut->getPointer();
9318   const int *srcArrPtr=srcArr->getConstPointer();
9319   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9320     {
9321       if(*it>=0 && *it<nbOfTuples)
9322         {
9323           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9324             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9325           else
9326             {
9327               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] !";
9328               throw INTERP_KERNEL::Exception(oss.str().c_str());
9329             }
9330         }
9331       else
9332         {
9333           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9334           throw INTERP_KERNEL::Exception(oss.str().c_str());
9335         }
9336     }
9337 }
9338
9339 /*!
9340  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9341  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9342  * 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]].
9343  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9344  * A negative value in \b arrIn means that it is ignored.
9345  * 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.
9346  * 
9347  * \param [in] arrIn arr origin array from which the extraction will be done.
9348  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9349  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9350  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9351  */
9352 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9353 {
9354   int seed=0,nbOfDepthPeelingPerformed=0;
9355   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9356 }
9357
9358 /*!
9359  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9360  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9361  * 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]].
9362  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9363  * A negative value in \b arrIn means that it is ignored.
9364  * 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.
9365  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9366  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9367  * \param [in] arrIn arr origin array from which the extraction will be done.
9368  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9369  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9370  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9371  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9372  * \sa MEDCouplingUMesh::partitionBySpreadZone
9373  */
9374 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9375 {
9376   nbOfDepthPeelingPerformed=0;
9377   if(!arrIndxIn)
9378     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9379   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9380   if(nbOfTuples<=0)
9381     {
9382       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9383       return ret;
9384     }
9385   //
9386   std::vector<bool> fetched(nbOfTuples,false);
9387   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9388 }
9389
9390 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9391 {
9392   nbOfDepthPeelingPerformed=0;
9393   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9394     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9395   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9396   std::vector<bool> fetched2(nbOfTuples,false);
9397   int i=0;
9398   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9399     {
9400       if(*seedElt>=0 && *seedElt<nbOfTuples)
9401         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9402       else
9403         { 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()); }
9404     }
9405   const int *arrInPtr=arrIn->getConstPointer();
9406   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9407   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9408   std::vector<int> idsToFetch1(seedBg,seedEnd);
9409   std::vector<int> idsToFetch2;
9410   std::vector<int> *idsToFetch=&idsToFetch1;
9411   std::vector<int> *idsToFetchOther=&idsToFetch2;
9412   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9413     {
9414       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9415         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9416           if(!fetched[*it2])
9417             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9418       std::swap(idsToFetch,idsToFetchOther);
9419       idsToFetchOther->clear();
9420       nbOfDepthPeelingPerformed++;
9421     }
9422   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9423   i=0;
9424   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9425   int *retPtr=ret->getPointer();
9426   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9427     if(*it)
9428       *retPtr++=i;
9429   return ret.retn();
9430 }
9431
9432 /*!
9433  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9434  * 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
9435  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9436  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9437  *
9438  * \param [in] start begin of set of ids of the input extraction (included)
9439  * \param [in] end end of set of ids of the input extraction (excluded)
9440  * \param [in] step step of the set of ids in range mode.
9441  * \param [in] arrIn arr origin array from which the extraction will be done.
9442  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9443  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9444  * \param [in] srcArrIndex index array of \b srcArr
9445  * \param [out] arrOut the resulting array
9446  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9447  * 
9448  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9449  */
9450 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9451                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9452                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9453 {
9454   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9455     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9456   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9457   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9458   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9459   int offset=0;
9460   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9461   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9462   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9463   int it=start;
9464   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9465     {
9466       if(it>=0 && it<nbOfTuples)
9467         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9468       else
9469         {
9470           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9471           throw INTERP_KERNEL::Exception(oss.str().c_str());
9472         }
9473     }
9474   srcArrIndexPtr=srcArrIndex->getConstPointer();
9475   arrIo->alloc(nbOfTuples+1,1);
9476   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9477   const int *arrInPtr=arrIn->getConstPointer();
9478   const int *srcArrPtr=srcArr->getConstPointer();
9479   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9480   int *arroPtr=arro->getPointer();
9481   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9482     {
9483       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9484       if(pos<0)
9485         {
9486           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9487           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9488         }
9489       else
9490         {
9491           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9492           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9493         }
9494     }
9495   arrOut=arro.retn();
9496   arrIndexOut=arrIo.retn();
9497 }
9498
9499 /*!
9500  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9501  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9502  *
9503  * \param [in] start begin of set of ids of the input extraction (included)
9504  * \param [in] end end of set of ids of the input extraction (excluded)
9505  * \param [in] step step of the set of ids in range mode.
9506  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9507  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9508  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9509  * \param [in] srcArrIndex index array of \b srcArr
9510  * 
9511  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9512  */
9513 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9514                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9515 {
9516   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9517     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9518   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9519   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9520   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9521   int *arrInOutPtr=arrInOut->getPointer();
9522   const int *srcArrPtr=srcArr->getConstPointer();
9523   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9524   int it=start;
9525   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9526     {
9527       if(it>=0 && it<nbOfTuples)
9528         {
9529           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9530             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9531           else
9532             {
9533               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9534               throw INTERP_KERNEL::Exception(oss.str().c_str());
9535             }
9536         }
9537       else
9538         {
9539           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9540           throw INTERP_KERNEL::Exception(oss.str().c_str());
9541         }
9542     }
9543 }
9544
9545 /*!
9546  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9547  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9548  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9549  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9550  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9551  * 
9552  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9553  */
9554 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
9555 {
9556   checkFullyDefined();
9557   int mdim=getMeshDimension();
9558   int spaceDim=getSpaceDimension();
9559   if(mdim!=spaceDim)
9560     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9561   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9562   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9563   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9564   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9565   ret->setCoords(getCoords());
9566   ret->allocateCells((int)partition.size());
9567   //
9568   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9569     {
9570       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9571       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9572       switch(mdim)
9573         {
9574         case 2:
9575           cell=tmp->buildUnionOf2DMesh();
9576           break;
9577         case 3:
9578           cell=tmp->buildUnionOf3DMesh();
9579           break;
9580         default:
9581           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9582         }
9583       
9584       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9585     }
9586   //
9587   ret->finishInsertingCells();
9588   return ret.retn();
9589 }
9590
9591 /*!
9592  * This method partitions \b this into contiguous zone.
9593  * This method only needs a well defined connectivity. Coordinates are not considered here.
9594  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9595  */
9596 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
9597 {
9598   int nbOfCellsCur=getNumberOfCells();
9599   std::vector<DataArrayInt *> ret;
9600   if(nbOfCellsCur<=0)
9601     return ret;
9602   DataArrayInt *neigh=0,*neighI=0;
9603   computeNeighborsOfCells(neigh,neighI);
9604   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9605   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9606   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9607   int seed=0;
9608   while(seed<nbOfCellsCur)
9609     {
9610       int nbOfPeelPerformed=0;
9611       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9612       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9613     }
9614   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9615     ret.push_back((*it).retn());
9616   return ret;
9617 }
9618
9619 /*!
9620  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9621  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9622  *
9623  * \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.
9624  * \return a newly allocated DataArrayInt to be managed by the caller.
9625  * \throw In case of \a code has not the right format (typically of size 3*n)
9626  */
9627 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
9628 {
9629   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9630   std::size_t nb=code.size()/3;
9631   if(code.size()%3!=0)
9632     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9633   ret->alloc((int)nb,2);
9634   int *retPtr=ret->getPointer();
9635   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9636     {
9637       retPtr[0]=code[3*i+2];
9638       retPtr[1]=code[3*i+2]+code[3*i+1];
9639     }
9640   return ret.retn();
9641 }
9642
9643 /*!
9644  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9645  * All cells in \a this are expected to be linear 3D cells.
9646  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9647  * It leads to an increase to number of cells.
9648  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9649  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
9650  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9651  *
9652  * \param [in] policy - the policy of splitting that must be in (PLANAR_FACE_5, PLANAR_FACE_6, GENERAL_24, GENERAL_48). The policy will be used only for INTERP_KERNEL::NORM_HEXA8 cells.
9653  *                      For all other cells, the splitting policy will be ignored.
9654  * \param [out] nbOfAdditionalPoints - number of nodes added to \c this->_coords. If > 0 a new coordinates object will be constructed result of the aggregation of the old one and the new points added. 
9655  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9656  *          an id of old cell producing it. The caller is to delete this array using
9657  *         decrRef() as it is no more needed.
9658  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9659  *
9660  * \warning This method operates on each cells in this independantly ! So it can leads to non conform mesh in returned value ! If you expect to have a conform mesh in output
9661  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
9662  * 
9663  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9664  * \throw If \a this is not fully constituted with linear 3D cells.
9665  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
9666  */
9667 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
9668 {
9669   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9670   checkConnectivityFullyDefined();
9671   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9672     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9673   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9674   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
9675   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9676   int *retPt(ret->getPointer());
9677   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9678   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9679   const int *oldc(_nodal_connec->begin());
9680   const int *oldci(_nodal_connec_index->begin());
9681   const double *coords(_coords->begin());
9682   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9683     {
9684       std::vector<int> a; std::vector<double> b;
9685       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9686       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9687       const int *aa(&a[0]);
9688       if(!b.empty())
9689         {
9690           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9691             if(*it<0)
9692               *it=(-(*(it))-1+nbNodes);
9693           addPts->insertAtTheEnd(b.begin(),b.end());
9694           nbNodes+=(int)b.size()/3;
9695         }
9696       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9697         newConn->insertAtTheEnd(aa,aa+4);
9698     }
9699   if(!addPts->empty())
9700     {
9701       addPts->rearrange(3);
9702       nbOfAdditionalPoints=addPts->getNumberOfTuples();
9703       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9704       ret0->setCoords(addPts);
9705     }
9706   else
9707     {
9708       nbOfAdditionalPoints=0;
9709       ret0->setCoords(getCoords());
9710     }
9711   ret0->setNodalConnectivity(newConn);
9712   //
9713   ret->computeOffsets2();
9714   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
9715   return ret0.retn();
9716 }
9717
9718 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9719                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9720 {
9721   if(mesh)
9722     {
9723       mesh->incrRef();
9724       _nb_cell=mesh->getNumberOfCells();
9725     }
9726 }
9727
9728 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9729 {
9730   if(_mesh)
9731     _mesh->decrRef();
9732   if(_own_cell)
9733     delete _cell;
9734 }
9735
9736 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9737                                                                                                                                _own_cell(false),_cell_id(bg-1),
9738                                                                                                                                _nb_cell(end)
9739 {
9740   if(mesh)
9741     mesh->incrRef();
9742 }
9743
9744 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9745 {
9746   _cell_id++;
9747   if(_cell_id<_nb_cell)
9748     {
9749       _cell->next();
9750       return _cell;
9751     }
9752   else
9753     return 0;
9754 }
9755
9756 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9757 {
9758   if(_mesh)
9759     _mesh->incrRef();
9760 }
9761
9762 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9763 {
9764   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9765 }
9766
9767 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9768 {
9769   if(_mesh)
9770     _mesh->decrRef();
9771 }
9772
9773 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9774                                                                                                                                                                   _itc(itc),
9775                                                                                                                                                                   _bg(bg),_end(end)
9776 {
9777   if(_mesh)
9778     _mesh->incrRef();
9779 }
9780
9781 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9782 {
9783   if(_mesh)
9784     _mesh->decrRef();
9785 }
9786
9787 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9788 {
9789   return _type;
9790 }
9791
9792 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9793 {
9794   return _end-_bg;
9795 }
9796
9797 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9798 {
9799   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9800 }
9801
9802 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9803 {
9804   if(mesh)
9805     {
9806       mesh->incrRef();
9807       _nb_cell=mesh->getNumberOfCells();
9808     }
9809 }
9810
9811 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9812 {
9813   if(_mesh)
9814     _mesh->decrRef();
9815   delete _cell;
9816 }
9817
9818 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9819 {
9820   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9821   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9822   if(_cell_id<_nb_cell)
9823     {
9824       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9825       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9826       int startId=_cell_id;
9827       _cell_id+=nbOfElems;
9828       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9829     }
9830   else
9831     return 0;
9832 }
9833
9834 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9835 {
9836   if(mesh)
9837     {
9838       _conn=mesh->getNodalConnectivity()->getPointer();
9839       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9840     }
9841 }
9842
9843 void MEDCouplingUMeshCell::next()
9844 {
9845   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9846     {
9847       _conn+=_conn_lgth;
9848       _conn_indx++;
9849     }
9850   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9851 }
9852
9853 std::string MEDCouplingUMeshCell::repr() const
9854 {
9855   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9856     {
9857       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9858       oss << " : ";
9859       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9860       return oss.str();
9861     }
9862   else
9863     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9864 }
9865
9866 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9867 {
9868   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9869     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9870   else
9871     return INTERP_KERNEL::NORM_ERROR;
9872 }
9873
9874 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9875 {
9876   lgth=_conn_lgth;
9877   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9878     return _conn;
9879   else
9880     return 0;
9881 }