Salome HOME
2d46d5cfa56b50b79788bce94bcb82ed9d051812
[tools/medcoupling.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       const int *connOld(_nodal_connec->getConstPointer());
1045       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1046       std::vector<bool> toBeDone(nbOfCells,false);
1047       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1048         {
1049           if(*iter>=0 && *iter<nbOfCells)
1050             toBeDone[*iter]=true;
1051           else
1052             {
1053               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1054               oss << " in range [0," << nbOfCells << ") !";
1055               throw INTERP_KERNEL::Exception(oss.str().c_str());
1056             }
1057         }
1058       for(int cellId=0;cellId<nbOfCells;cellId++)
1059         {
1060           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1061           int lgthOld(posP1-pos-1);
1062           if(toBeDone[cellId])
1063             {
1064               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1065               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1066               int *tmp(new int[nbOfFaces*lgthOld+1]);
1067               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1068               for(unsigned j=0;j<nbOfFaces;j++)
1069                 {
1070                   INTERP_KERNEL::NormalizedCellType type;
1071                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1072                   work+=offset;
1073                   *work++=-1;
1074                 }
1075               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1076               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1077               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1078               delete [] tmp;
1079             }
1080           else
1081             {
1082               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1083               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1084             }
1085         }
1086       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1087     }
1088   computeTypes();
1089 }
1090
1091 /*!
1092  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1093  * polyhedrons (if \a this is a 3D mesh).
1094  *  \warning As this method is purely for user-friendliness and no optimization is
1095  *          done to avoid construction of a useless vector, this method can be costly
1096  *          in memory.
1097  *  \throw If the coordinates array is not set.
1098  *  \throw If the nodal connectivity of cells is node defined.
1099  *  \throw If dimension of \a this mesh is not either 2 or 3.
1100  */
1101 void MEDCouplingUMesh::convertAllToPoly()
1102 {
1103   int nbOfCells=getNumberOfCells();
1104   std::vector<int> cellIds(nbOfCells);
1105   for(int i=0;i<nbOfCells;i++)
1106     cellIds[i]=i;
1107   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1108 }
1109
1110 /*!
1111  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1112  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1113  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1114  * base facet of the volume and the second half of nodes describes an opposite facet
1115  * having the same number of nodes as the base one. This method converts such
1116  * connectivity to a valid polyhedral format where connectivity of each facet is
1117  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1118  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1119  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1120  * a correct orientation of the first facet of a polyhedron, else orientation of a
1121  * corrected cell is reverse.<br>
1122  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1123  * it releases the user from boring description of polyhedra connectivity in the valid
1124  * format.
1125  *  \throw If \a this->getMeshDimension() != 3.
1126  *  \throw If \a this->getSpaceDimension() != 3.
1127  *  \throw If the nodal connectivity of cells is not defined.
1128  *  \throw If the coordinates array is not set.
1129  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1130  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1131  *
1132  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1133  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1134  */
1135 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1136 {
1137   checkFullyDefined();
1138   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1139     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1140   int nbOfCells=getNumberOfCells();
1141   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1142   newCi->alloc(nbOfCells+1,1);
1143   int *newci=newCi->getPointer();
1144   const int *ci=_nodal_connec_index->getConstPointer();
1145   const int *c=_nodal_connec->getConstPointer();
1146   newci[0]=0;
1147   for(int i=0;i<nbOfCells;i++)
1148     {
1149       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1150       if(type==INTERP_KERNEL::NORM_POLYHED)
1151         {
1152           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1153             {
1154               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1155               throw INTERP_KERNEL::Exception(oss.str().c_str());
1156             }
1157           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1158           if(n2%2!=0)
1159             {
1160               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 !";
1161               throw INTERP_KERNEL::Exception(oss.str().c_str());
1162             }
1163           int n1=(int)(n2/2);
1164           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)
1165         }
1166       else
1167         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1168     }
1169   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1170   newC->alloc(newci[nbOfCells],1);
1171   int *newc=newC->getPointer();
1172   for(int i=0;i<nbOfCells;i++)
1173     {
1174       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1175       if(type==INTERP_KERNEL::NORM_POLYHED)
1176         {
1177           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1178           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1179           *newc++=-1;
1180           for(std::size_t j=0;j<n1;j++)
1181             {
1182               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1183               newc[n1+5*j]=-1;
1184               newc[n1+5*j+1]=c[ci[i]+1+j];
1185               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1186               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1187               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1188             }
1189           newc+=n1*6;
1190         }
1191       else
1192         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1193     }
1194   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1195   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1196 }
1197
1198
1199 /*!
1200  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1201  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1202  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1203  *          to write this mesh to the MED file, its cells must be sorted using
1204  *          sortCellsInMEDFileFrmt().
1205  * \return \c true if at least one cell has been converted, \c false else. In the
1206  *         last case the nodal connectivity remains unchanged.
1207  * \throw If the coordinates array is not set.
1208  * \throw If the nodal connectivity of cells is not defined.
1209  * \throw If \a this->getMeshDimension() < 0.
1210  */
1211 bool MEDCouplingUMesh::unPolyze()
1212 {
1213   checkFullyDefined();
1214   int mdim=getMeshDimension();
1215   if(mdim<0)
1216     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1217   if(mdim<=1)
1218     return false;
1219   int nbOfCells=getNumberOfCells();
1220   if(nbOfCells<1)
1221     return false;
1222   int initMeshLgth=getMeshLength();
1223   int *conn=_nodal_connec->getPointer();
1224   int *index=_nodal_connec_index->getPointer();
1225   int posOfCurCell=0;
1226   int newPos=0;
1227   int lgthOfCurCell;
1228   bool ret=false;
1229   for(int i=0;i<nbOfCells;i++)
1230     {
1231       lgthOfCurCell=index[i+1]-posOfCurCell;
1232       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1233       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1234       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1235       int newLgth;
1236       if(cm.isDynamic())
1237         {
1238           switch(cm.getDimension())
1239             {
1240             case 2:
1241               {
1242                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1243                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1244                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1245                 break;
1246               }
1247             case 3:
1248               {
1249                 int nbOfFaces,lgthOfPolyhConn;
1250                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1251                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1252                 break;
1253               }
1254             case 1:
1255               {
1256                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1257                 break;
1258               }
1259             }
1260           ret=ret || (newType!=type);
1261           conn[newPos]=newType;
1262           newPos+=newLgth+1;
1263           posOfCurCell=index[i+1];
1264           index[i+1]=newPos;
1265         }
1266       else
1267         {
1268           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1269           newPos+=lgthOfCurCell;
1270           posOfCurCell+=lgthOfCurCell;
1271           index[i+1]=newPos;
1272         }
1273     }
1274   if(newPos!=initMeshLgth)
1275     _nodal_connec->reAlloc(newPos);
1276   if(ret)
1277     computeTypes();
1278   return ret;
1279 }
1280
1281 /*!
1282  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1283  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1284  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1285  *
1286  * \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 
1287  *             precision.
1288  */
1289 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1290 {
1291   checkFullyDefined();
1292   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1293     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1294   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1295   coords->recenterForMaxPrecision(eps);
1296   //
1297   int nbOfCells=getNumberOfCells();
1298   const int *conn=_nodal_connec->getConstPointer();
1299   const int *index=_nodal_connec_index->getConstPointer();
1300   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1301   connINew->alloc(nbOfCells+1,1);
1302   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1303   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1304   bool changed=false;
1305   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1306     {
1307       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1308         {
1309           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1310           changed=true;
1311         }
1312       else
1313         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1314       *connINewPtr=connNew->getNumberOfTuples();
1315     }
1316   if(changed)
1317     setConnectivity(connNew,connINew,false);
1318 }
1319
1320 /*!
1321  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1322  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1323  * the format of returned DataArrayInt instance.
1324  * 
1325  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1326  * \sa MEDCouplingUMesh::getNodeIdsInUse
1327  */
1328 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1329 {
1330   checkConnectivityFullyDefined();
1331   int nbOfCells=getNumberOfCells();
1332   const int *connIndex=_nodal_connec_index->getConstPointer();
1333   const int *conn=_nodal_connec->getConstPointer();
1334   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1335   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1336   std::vector<bool> retS(maxElt,false);
1337   for(int i=0;i<nbOfCells;i++)
1338     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1339       if(conn[j]>=0)
1340         retS[conn[j]]=true;
1341   int sz=0;
1342   for(int i=0;i<maxElt;i++)
1343     if(retS[i])
1344       sz++;
1345   DataArrayInt *ret=DataArrayInt::New();
1346   ret->alloc(sz,1);
1347   int *retPtr=ret->getPointer();
1348   for(int i=0;i<maxElt;i++)
1349     if(retS[i])
1350       *retPtr++=i;
1351   return ret;
1352 }
1353
1354 /*!
1355  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1356  * \sa MEDCouplingUMesh::getNodeIdsInUse
1357  */
1358 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1359 {
1360   int nbOfNodes=(int)nodeIdsInUse.size();
1361   int nbOfCells=getNumberOfCells();
1362   const int *connIndex=_nodal_connec_index->getConstPointer();
1363   const int *conn=_nodal_connec->getConstPointer();
1364   for(int i=0;i<nbOfCells;i++)
1365     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1366       if(conn[j]>=0)
1367         {
1368           if(conn[j]<nbOfNodes)
1369             nodeIdsInUse[conn[j]]=true;
1370           else
1371             {
1372               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1373               throw INTERP_KERNEL::Exception(oss.str().c_str());
1374             }
1375         }
1376 }
1377
1378 /*!
1379  * Finds nodes not used in any cell and returns an array giving a new id to every node
1380  * by excluding the unused nodes, for which the array holds -1. The result array is
1381  * a mapping in "Old to New" mode. 
1382  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1383  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1384  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1385  *          if the node is unused or a new id else. The caller is to delete this
1386  *          array using decrRef() as it is no more needed.  
1387  *  \throw If the coordinates array is not set.
1388  *  \throw If the nodal connectivity of cells is not defined.
1389  *  \throw If the nodal connectivity includes an invalid id.
1390  *
1391  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1392  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1393  * \sa computeNodeIdsAlg()
1394  */
1395 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1396 {
1397   nbrOfNodesInUse=-1;
1398   int nbOfNodes=getNumberOfNodes();
1399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1400   ret->alloc(nbOfNodes,1);
1401   int *traducer=ret->getPointer();
1402   std::fill(traducer,traducer+nbOfNodes,-1);
1403   int nbOfCells=getNumberOfCells();
1404   const int *connIndex=_nodal_connec_index->getConstPointer();
1405   const int *conn=_nodal_connec->getConstPointer();
1406   for(int i=0;i<nbOfCells;i++)
1407     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1408       if(conn[j]>=0)
1409         {
1410           if(conn[j]<nbOfNodes)
1411             traducer[conn[j]]=1;
1412           else
1413             {
1414               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1415               throw INTERP_KERNEL::Exception(oss.str().c_str());
1416             }
1417         }
1418   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1419   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1420   return ret.retn();
1421 }
1422
1423 /*!
1424  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1425  * For each cell in \b this the number of nodes constituting cell is computed.
1426  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1427  * So for pohyhedrons some nodes can be counted several times in the returned result.
1428  * 
1429  * \return a newly allocated array
1430  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1431  */
1432 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1433 {
1434   checkConnectivityFullyDefined();
1435   int nbOfCells=getNumberOfCells();
1436   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1437   ret->alloc(nbOfCells,1);
1438   int *retPtr=ret->getPointer();
1439   const int *conn=getNodalConnectivity()->getConstPointer();
1440   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1441   for(int i=0;i<nbOfCells;i++,retPtr++)
1442     {
1443       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1444         *retPtr=connI[i+1]-connI[i]-1;
1445       else
1446         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1447     }
1448   return ret.retn();
1449 }
1450
1451 /*!
1452  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1453  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1454  *
1455  * \return DataArrayInt * - new object to be deallocated by the caller.
1456  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1457  */
1458 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1459 {
1460   checkConnectivityFullyDefined();
1461   int nbOfCells=getNumberOfCells();
1462   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1463   ret->alloc(nbOfCells,1);
1464   int *retPtr=ret->getPointer();
1465   const int *conn=getNodalConnectivity()->getConstPointer();
1466   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1467   for(int i=0;i<nbOfCells;i++,retPtr++)
1468     {
1469       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1470       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1471         *retPtr=(int)s.size();
1472       else
1473         {
1474           s.erase(-1);
1475           *retPtr=(int)s.size();
1476         }
1477     }
1478   return ret.retn();
1479 }
1480
1481 /*!
1482  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1483  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1484  * 
1485  * \return a newly allocated array
1486  */
1487 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1488 {
1489   checkConnectivityFullyDefined();
1490   int nbOfCells=getNumberOfCells();
1491   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1492   ret->alloc(nbOfCells,1);
1493   int *retPtr=ret->getPointer();
1494   const int *conn=getNodalConnectivity()->getConstPointer();
1495   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1496   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1497     {
1498       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1499       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1500     }
1501   return ret.retn();
1502 }
1503
1504 /*!
1505  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1506  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1507  * array mean that the corresponding old node is no more used. 
1508  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1509  *           this->getNumberOfNodes() before call of this method. The caller is to
1510  *           delete this array using decrRef() as it is no more needed. 
1511  *  \throw If the coordinates array is not set.
1512  *  \throw If the nodal connectivity of cells is not defined.
1513  *  \throw If the nodal connectivity includes an invalid id.
1514  *
1515  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1516  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1517  */
1518 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1519 {
1520   return MEDCouplingPointSet::zipCoordsTraducer();
1521 }
1522
1523 /*!
1524  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1525  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1526  */
1527 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1528 {
1529   switch(compType)
1530     {
1531     case 0:
1532       return AreCellsEqual0(conn,connI,cell1,cell2);
1533     case 1:
1534       return AreCellsEqual1(conn,connI,cell1,cell2);
1535     case 2:
1536       return AreCellsEqual2(conn,connI,cell1,cell2);
1537     case 3:
1538       return AreCellsEqual3(conn,connI,cell1,cell2);
1539     case 7:
1540       return AreCellsEqual7(conn,connI,cell1,cell2);
1541     }
1542   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1543 }
1544
1545 /*!
1546  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1547  */
1548 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1549 {
1550   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1551     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1552   return 0;
1553 }
1554
1555 /*!
1556  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1557  */
1558 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1559 {
1560   int sz=connI[cell1+1]-connI[cell1];
1561   if(sz==connI[cell2+1]-connI[cell2])
1562     {
1563       if(conn[connI[cell1]]==conn[connI[cell2]])
1564         {
1565           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1566           unsigned dim=cm.getDimension();
1567           if(dim!=3)
1568             {
1569               if(dim!=1)
1570                 {
1571                   int sz1=2*(sz-1);
1572                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1573                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1574                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1575                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1576                   return work!=tmp+sz1?1:0;
1577                 }
1578               else
1579                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1580             }
1581           else
1582             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1583         }
1584     }
1585   return 0;
1586 }
1587
1588 /*!
1589  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1590  */
1591 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1592 {
1593   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1594     {
1595       if(conn[connI[cell1]]==conn[connI[cell2]])
1596         {
1597           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1598           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1599           return s1==s2?1:0;
1600         }
1601     }
1602   return 0;
1603 }
1604
1605 /*!
1606  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1607  */
1608 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1609 {
1610   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1611     {
1612       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1613       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1614       return s1==s2?1:0;
1615     }
1616   return 0;
1617 }
1618
1619 /*!
1620  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1621  */
1622 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1623 {
1624   int sz=connI[cell1+1]-connI[cell1];
1625   if(sz==connI[cell2+1]-connI[cell2])
1626     {
1627       if(conn[connI[cell1]]==conn[connI[cell2]])
1628         {
1629           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1630           unsigned dim=cm.getDimension();
1631           if(dim!=3)
1632             {
1633               if(dim!=1)
1634                 {
1635                   int sz1=2*(sz-1);
1636                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1637                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1638                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1639                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1640                   if(work!=tmp+sz1)
1641                     return 1;
1642                   else
1643                     {
1644                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1645                       std::reverse_iterator<int *> it2((int *)tmp);
1646                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1647                         return 2;
1648                       else
1649                         return 0;
1650                     }
1651                   
1652                   return work!=tmp+sz1?1:0;
1653                 }
1654               else
1655                 {//case of SEG2 and SEG3
1656                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1657                     return 1;
1658                   if(!cm.isQuadratic())
1659                     {
1660                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1661                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1662                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1663                         return 2;
1664                       return 0;
1665                     }
1666                   else
1667                     {
1668                       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])
1669                         return 2;
1670                       return 0;
1671                     }
1672                 }
1673             }
1674           else
1675             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1676         }
1677     }
1678   return 0;
1679 }
1680
1681 /*!
1682  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1683  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1684  * and result remains unchanged.
1685  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1686  * If in 'candidates' pool -1 value is considered as an empty value.
1687  * WARNING this method returns only ONE set of result !
1688  */
1689 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1690 {
1691   if(candidates.size()<1)
1692     return false;
1693   bool ret=false;
1694   std::vector<int>::const_iterator iter=candidates.begin();
1695   int start=(*iter++);
1696   for(;iter!=candidates.end();iter++)
1697     {
1698       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1699       if(status!=0)
1700         {
1701           if(!ret)
1702             {
1703               result->pushBackSilent(start);
1704               ret=true;
1705             }
1706           if(status==1)
1707             result->pushBackSilent(*iter);
1708           else
1709             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1710         }
1711     }
1712   return ret;
1713 }
1714
1715 /*!
1716  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1717  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1718  *
1719  * \param [in] compType input specifying the technique used to compare cells each other.
1720  *   - 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.
1721  *   - 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)
1722  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1723  *   - 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
1724  * can be used for users not sensitive to orientation of cell
1725  * \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.
1726  * \param [out] commonCells
1727  * \param [out] commonCellsI
1728  * \return the correspondance array old to new in a newly allocated array.
1729  * 
1730  */
1731 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1732 {
1733   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1734   getReverseNodalConnectivity(revNodal,revNodalI);
1735   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1736 }
1737
1738 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1739                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1740 {
1741   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1742   int nbOfCells=nodalI->getNumberOfTuples()-1;
1743   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1744   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1745   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1746   std::vector<bool> isFetched(nbOfCells,false);
1747   if(startCellId==0)
1748     {
1749       for(int i=0;i<nbOfCells;i++)
1750         {
1751           if(!isFetched[i])
1752             {
1753               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1754               std::vector<int> v,v2;
1755               if(connOfNode!=connPtr+connIPtr[i+1])
1756                 {
1757                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1758                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1759                   connOfNode++;
1760                 }
1761               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1762                 if(*connOfNode>=0)
1763                   {
1764                     v=v2;
1765                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1766                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1767                     v2.resize(std::distance(v2.begin(),it));
1768                   }
1769               if(v2.size()>1)
1770                 {
1771                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1772                     {
1773                       int pos=commonCellsI->back();
1774                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1775                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1776                         isFetched[*it]=true;
1777                     }
1778                 }
1779             }
1780         }
1781     }
1782   else
1783     {
1784       for(int i=startCellId;i<nbOfCells;i++)
1785         {
1786           if(!isFetched[i])
1787             {
1788               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1789               std::vector<int> v,v2;
1790               if(connOfNode!=connPtr+connIPtr[i+1])
1791                 {
1792                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1793                   connOfNode++;
1794                 }
1795               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1796                 if(*connOfNode>=0)
1797                   {
1798                     v=v2;
1799                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1800                     v2.resize(std::distance(v2.begin(),it));
1801                   }
1802               if(v2.size()>1)
1803                 {
1804                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1805                     {
1806                       int pos=commonCellsI->back();
1807                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1808                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1809                         isFetched[*it]=true;
1810                     }
1811                 }
1812             }
1813         }
1814     }
1815   commonCellsArr=commonCells.retn();
1816   commonCellsIArr=commonCellsI.retn();
1817 }
1818
1819 /*!
1820  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1821  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1822  * than \a other->getNumberOfCells() in the returned array means that there is no
1823  * corresponding cell in \a this mesh.
1824  * It is expected that \a this and \a other meshes share the same node coordinates
1825  * array, if it is not so an exception is thrown. 
1826  *  \param [in] other - the mesh to compare with.
1827  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1828  *         valid values [0,1,2], see zipConnectivityTraducer().
1829  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1830  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1831  *         values. The caller is to delete this array using
1832  *         decrRef() as it is no more needed.
1833  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1834  *         mesh.
1835  *
1836  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1837  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1838  *  \sa checkDeepEquivalOnSameNodesWith()
1839  *  \sa checkGeoEquivalWith()
1840  */
1841 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1842 {
1843   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1844   int nbOfCells=getNumberOfCells();
1845   static const int possibleCompType[]={0,1,2};
1846   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1847     {
1848       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1849       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1850       oss << " !";
1851       throw INTERP_KERNEL::Exception(oss.str().c_str());
1852     }
1853   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1854   arr=o2n->substr(nbOfCells);
1855   arr->setName(other->getName());
1856   int tmp;
1857   if(other->getNumberOfCells()==0)
1858     return true;
1859   return arr->getMaxValue(tmp)<nbOfCells;
1860 }
1861
1862 /*!
1863  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1864  * This method tries to determine if \b other is fully included in \b this.
1865  * The main difference is that this method is not expected to throw exception.
1866  * This method has two outputs :
1867  *
1868  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1869  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1870  */
1871 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1872 {
1873   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1874   DataArrayInt *commonCells=0,*commonCellsI=0;
1875   int thisNbCells=getNumberOfCells();
1876   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1878   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1879   int otherNbCells=other->getNumberOfCells();
1880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1881   arr2->alloc(otherNbCells,1);
1882   arr2->fillWithZero();
1883   int *arr2Ptr=arr2->getPointer();
1884   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1885   for(int i=0;i<nbOfCommon;i++)
1886     {
1887       int start=commonCellsPtr[commonCellsIPtr[i]];
1888       if(start<thisNbCells)
1889         {
1890           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1891             {
1892               int sig=commonCellsPtr[j]>0?1:-1;
1893               int val=std::abs(commonCellsPtr[j])-1;
1894               if(val>=thisNbCells)
1895                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1896             }
1897         }
1898     }
1899   arr2->setName(other->getName());
1900   if(arr2->presenceOfValue(0))
1901     return false;
1902   arr=arr2.retn();
1903   return true;
1904 }
1905
1906 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1907 {
1908   if(!other)
1909     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1910   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1911   if(!otherC)
1912     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1913   std::vector<const MEDCouplingUMesh *> ms(2);
1914   ms[0]=this;
1915   ms[1]=otherC;
1916   return MergeUMeshesOnSameCoords(ms);
1917 }
1918
1919 /*!
1920  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1921  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1922  * cellIds is not given explicitely but by a range python like.
1923  * 
1924  * \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.
1925  * \return a newly allocated
1926  * 
1927  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1928  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1929  */
1930 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
1931 {
1932   if(getMeshDimension()!=-1)
1933     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1934   else
1935     {
1936       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1937       if(newNbOfCells!=1)
1938         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1939       if(start!=0)
1940         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1941       incrRef();
1942       return const_cast<MEDCouplingUMesh *>(this);
1943     }
1944 }
1945
1946 /*!
1947  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1948  * The result mesh shares or not the node coordinates array with \a this mesh depending
1949  * on \a keepCoords parameter.
1950  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1951  *           to write this mesh to the MED file, its cells must be sorted using
1952  *           sortCellsInMEDFileFrmt().
1953  *  \param [in] begin - an array of cell ids to include to the new mesh.
1954  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1955  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1956  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1957  *         by calling zipCoords().
1958  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1959  *         to delete this mesh using decrRef() as it is no more needed. 
1960  *  \throw If the coordinates array is not set.
1961  *  \throw If the nodal connectivity of cells is not defined.
1962  *  \throw If any cell id in the array \a begin is not valid.
1963  *
1964  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1965  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1966  */
1967 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1968 {
1969   if(getMeshDimension()!=-1)
1970     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1971   else
1972     {
1973       if(end-begin!=1)
1974         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1975       if(begin[0]!=0)
1976         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1977       incrRef();
1978       return const_cast<MEDCouplingUMesh *>(this);
1979     }
1980 }
1981
1982 /*!
1983  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1984  *
1985  * 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.
1986  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1987  * The number of cells of \b this will remain the same with this method.
1988  *
1989  * \param [in] begin begin of cell ids (included) of cells in this to assign
1990  * \param [in] end end of cell ids (excluded) of cells in this to assign
1991  * \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 ).
1992  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1993  */
1994 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
1995 {
1996   checkConnectivityFullyDefined();
1997   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1998   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1999     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2000   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2001     {
2002       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2003       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2004       throw INTERP_KERNEL::Exception(oss.str().c_str());
2005     }
2006   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2007   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2008     {
2009       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2010       throw INTERP_KERNEL::Exception(oss.str().c_str());
2011     }
2012   int nbOfCells=getNumberOfCells();
2013   bool easyAssign=true;
2014   const int *connI=_nodal_connec_index->getConstPointer();
2015   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2016   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2017     {
2018       if(*it>=0 && *it<nbOfCells)
2019         {
2020           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2021         }
2022       else
2023         {
2024           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2025           throw INTERP_KERNEL::Exception(oss.str().c_str());
2026         }
2027     }
2028   if(easyAssign)
2029     {
2030       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2031       computeTypes();
2032     }
2033   else
2034     {
2035       DataArrayInt *arrOut=0,*arrIOut=0;
2036       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2037                                                arrOut,arrIOut);
2038       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2039       setConnectivity(arrOut,arrIOut,true);
2040     }
2041 }
2042
2043 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2044 {
2045   checkConnectivityFullyDefined();
2046   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2047   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2048     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2049   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2050     {
2051       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2052       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2053       throw INTERP_KERNEL::Exception(oss.str().c_str());
2054     }
2055   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2056   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2057     {
2058       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2059       throw INTERP_KERNEL::Exception(oss.str().c_str());
2060     }
2061   int nbOfCells=getNumberOfCells();
2062   bool easyAssign=true;
2063   const int *connI=_nodal_connec_index->getConstPointer();
2064   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2065   int it=start;
2066   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2067     {
2068       if(it>=0 && it<nbOfCells)
2069         {
2070           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2071         }
2072       else
2073         {
2074           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2075           throw INTERP_KERNEL::Exception(oss.str().c_str());
2076         }
2077     }
2078   if(easyAssign)
2079     {
2080       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2081       computeTypes();
2082     }
2083   else
2084     {
2085       DataArrayInt *arrOut=0,*arrIOut=0;
2086       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2087                                                 arrOut,arrIOut);
2088       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2089       setConnectivity(arrOut,arrIOut,true);
2090     }
2091 }                      
2092
2093 /*!
2094  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2095  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2096  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2097  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2098  *
2099  * \param [in] begin input start of array of node ids.
2100  * \param [in] end input end of array of node ids.
2101  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2102  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2103  */
2104 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2105 {
2106   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2107   checkConnectivityFullyDefined();
2108   int tmp=-1;
2109   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2110   std::vector<bool> fastFinder(sz,false);
2111   for(const int *work=begin;work!=end;work++)
2112     if(*work>=0 && *work<sz)
2113       fastFinder[*work]=true;
2114   int nbOfCells=getNumberOfCells();
2115   const int *conn=getNodalConnectivity()->getConstPointer();
2116   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2117   for(int i=0;i<nbOfCells;i++)
2118     {
2119       int ref=0,nbOfHit=0;
2120       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2121         if(*work2>=0)
2122           {
2123             ref++;
2124             if(fastFinder[*work2])
2125               nbOfHit++;
2126           }
2127       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2128         cellIdsKept->pushBackSilent(i);
2129     }
2130   cellIdsKeptArr=cellIdsKept.retn();
2131 }
2132
2133 /*!
2134  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2135  * this->getMeshDimension(), that bound some cells of \a this mesh.
2136  * The cells of lower dimension to include to the result mesh are selected basing on
2137  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2138  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2139  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2140  * created mesh shares the node coordinates array with \a this mesh. 
2141  *  \param [in] begin - the array of node ids.
2142  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2143  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2144  *         array \a begin are added, else cells whose any node is in the
2145  *         array \a begin are added.
2146  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2147  *         to delete this mesh using decrRef() as it is no more needed. 
2148  *  \throw If the coordinates array is not set.
2149  *  \throw If the nodal connectivity of cells is not defined.
2150  *  \throw If any node id in \a begin is not valid.
2151  *
2152  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2153  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2154  */
2155 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2156 {
2157   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2158   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2159   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2160   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2161   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2162 }
2163
2164 /*!
2165  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2166  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2167  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2168  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2169  *         by calling zipCoords().
2170  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2171  *         to delete this mesh using decrRef() as it is no more needed. 
2172  *  \throw If the coordinates array is not set.
2173  *  \throw If the nodal connectivity of cells is not defined.
2174  *
2175  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2176  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2177  */
2178 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2179 {
2180   DataArrayInt *desc=DataArrayInt::New();
2181   DataArrayInt *descIndx=DataArrayInt::New();
2182   DataArrayInt *revDesc=DataArrayInt::New();
2183   DataArrayInt *revDescIndx=DataArrayInt::New();
2184   //
2185   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2186   revDesc->decrRef();
2187   desc->decrRef();
2188   descIndx->decrRef();
2189   int nbOfCells=meshDM1->getNumberOfCells();
2190   const int *revDescIndxC=revDescIndx->getConstPointer();
2191   std::vector<int> boundaryCells;
2192   for(int i=0;i<nbOfCells;i++)
2193     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2194       boundaryCells.push_back(i);
2195   revDescIndx->decrRef();
2196   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2197   return ret;
2198 }
2199
2200 /*!
2201  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2202  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2203  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2204  */
2205 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2206 {
2207   checkFullyDefined();
2208   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2210   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2211   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2212   //
2213   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2214   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2215   //
2216   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2217   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2218   const int *revDescPtr=revDesc->getConstPointer();
2219   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2220   int nbOfCells=getNumberOfCells();
2221   std::vector<bool> ret1(nbOfCells,false);
2222   int sz=0;
2223   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2224     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2225       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2226   //
2227   DataArrayInt *ret2=DataArrayInt::New();
2228   ret2->alloc(sz,1);
2229   int *ret2Ptr=ret2->getPointer();
2230   sz=0;
2231   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2232     if(*it)
2233       *ret2Ptr++=sz;
2234   ret2->setName("BoundaryCells");
2235   return ret2;
2236 }
2237
2238 /*!
2239  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2240  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2241  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2242  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2243  *
2244  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2245  * This method method returns cells ids set s = s1 + s2 where :
2246  * 
2247  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2248  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2249  *
2250  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2251  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2252  *
2253  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2254  * \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
2255  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2256  */
2257 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2258 {
2259   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2260     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2261   checkConnectivityFullyDefined();
2262   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2263   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2264     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2265   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2266   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2267   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2268   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2269   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2270   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2271   DataArrayInt *idsOtherInConsti=0;
2272   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2273   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2274   if(!b)
2275     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2276   std::set<int> s1;
2277   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2278     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2280   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2281   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2282   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2283   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2284   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2285   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2286   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2287   neighThisPartAuto=0;
2288   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2289   const int li[2]={0,1};
2290   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2291   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2292   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2293   s_renum1->sort();
2294   //
2295   cellIdsRk0=s0arr.retn();
2296   cellIdsRk1=s_renum1.retn();
2297 }
2298
2299 /*!
2300  * 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
2301  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2302  * 
2303  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2304  */
2305 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2306 {
2307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2308   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2309   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2310   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2311   //
2312   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2313   revDesc=0; desc=0; descIndx=0;
2314   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2315   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2316   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2317 }
2318
2319 /*!
2320  * Finds nodes lying on the boundary of \a this mesh.
2321  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2322  *          nodes. The caller is to delete this array using decrRef() as it is no
2323  *          more needed.
2324  *  \throw If the coordinates array is not set.
2325  *  \throw If the nodal connectivity of cells is node defined.
2326  *
2327  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2328  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2329  */
2330 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2331 {
2332   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2333   return skin->computeFetchedNodeIds();
2334 }
2335
2336 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2337 {
2338   incrRef();
2339   return const_cast<MEDCouplingUMesh *>(this);
2340 }
2341
2342 /*!
2343  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2344  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2345  * 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.
2346  * 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.
2347  * 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.
2348  *
2349  * \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
2350  *             parameter is altered during the call.
2351  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2352  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2353  * \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.
2354  *
2355  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2356  */
2357 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2358                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2359 {
2360   checkFullyDefined();
2361   otherDimM1OnSameCoords.checkFullyDefined();
2362   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2363     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2364   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2365     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2366   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2367   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2369   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2370   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2371   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2372   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2373   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2374   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2375   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2376   //
2377   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2378   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2379   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2380   DataArrayInt *idsTmp=0;
2381   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2382   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2383   if(!b)
2384     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2385   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2386   DataArrayInt *tmp0=0,*tmp1=0;
2387   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2389   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2392   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2393   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2394   //
2395   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2396   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2397   nodeIdsToDuplicate=s3.retn();
2398 }
2399
2400 /*!
2401  * This method operates a modification of the connectivity and coords in \b this.
2402  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2403  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2404  * 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
2405  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2406  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2407  * 
2408  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2409  * 
2410  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2411  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2412  */
2413 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2414 {
2415   int nbOfNodes=getNumberOfNodes();
2416   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2417   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2418 }
2419
2420 /*!
2421  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2422  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2423  * This method is a generalization of shiftNodeNumbersInConn().
2424  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2425  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2426  *         this->getNumberOfNodes(), in "Old to New" mode. 
2427  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2428  *  \throw If the nodal connectivity of cells is not defined.
2429  *
2430  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2431  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2432  */
2433 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2434 {
2435   checkConnectivityFullyDefined();
2436   int *conn=getNodalConnectivity()->getPointer();
2437   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2438   int nbOfCells=getNumberOfCells();
2439   for(int i=0;i<nbOfCells;i++)
2440     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2441       {
2442         int& node=conn[iconn];
2443         if(node>=0)//avoid polyhedron separator
2444           {
2445             node=newNodeNumbersO2N[node];
2446           }
2447       }
2448   _nodal_connec->declareAsNew();
2449   updateTime();
2450 }
2451
2452 /*!
2453  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2454  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2455  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2456  * 
2457  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2458  */
2459 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2460 {
2461   checkConnectivityFullyDefined();
2462   int *conn=getNodalConnectivity()->getPointer();
2463   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2464   int nbOfCells=getNumberOfCells();
2465   for(int i=0;i<nbOfCells;i++)
2466     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2467       {
2468         int& node=conn[iconn];
2469         if(node>=0)//avoid polyhedron separator
2470           {
2471             node+=delta;
2472           }
2473       }
2474   _nodal_connec->declareAsNew();
2475   updateTime();
2476 }
2477
2478 /*!
2479  * This method operates a modification of the connectivity in \b this.
2480  * 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.
2481  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2482  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2483  * 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
2484  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2485  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2486  * 
2487  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2488  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2489  * 
2490  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2491  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2492  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2493  */
2494 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2495 {
2496   checkConnectivityFullyDefined();
2497   std::map<int,int> m;
2498   int val=offset;
2499   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2500     m[*work]=val;
2501   int *conn=getNodalConnectivity()->getPointer();
2502   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2503   int nbOfCells=getNumberOfCells();
2504   for(int i=0;i<nbOfCells;i++)
2505     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2506       {
2507         int& node=conn[iconn];
2508         if(node>=0)//avoid polyhedron separator
2509           {
2510             std::map<int,int>::iterator it=m.find(node);
2511             if(it!=m.end())
2512               node=(*it).second;
2513           }
2514       }
2515   updateTime();
2516 }
2517
2518 /*!
2519  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2520  *
2521  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2522  * After the call of this method the number of cells remains the same as before.
2523  *
2524  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2525  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2526  * be strictly in [0;this->getNumberOfCells()).
2527  *
2528  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2529  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2530  * should be contained in[0;this->getNumberOfCells()).
2531  * 
2532  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2533  */
2534 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2535 {
2536   checkConnectivityFullyDefined();
2537   int nbCells=getNumberOfCells();
2538   const int *array=old2NewBg;
2539   if(check)
2540     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2541   //
2542   const int *conn=_nodal_connec->getConstPointer();
2543   const int *connI=_nodal_connec_index->getConstPointer();
2544   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2545   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2546   const int *n2oPtr=n2o->begin();
2547   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2548   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2549   newConn->copyStringInfoFrom(*_nodal_connec);
2550   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2551   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2552   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2553   //
2554   int *newC=newConn->getPointer();
2555   int *newCI=newConnI->getPointer();
2556   int loc=0;
2557   newCI[0]=loc;
2558   for(int i=0;i<nbCells;i++)
2559     {
2560       int pos=n2oPtr[i];
2561       int nbOfElts=connI[pos+1]-connI[pos];
2562       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2563       loc+=nbOfElts;
2564       newCI[i+1]=loc;
2565     }
2566   //
2567   setConnectivity(newConn,newConnI);
2568   if(check)
2569     free(const_cast<int *>(array));
2570 }
2571
2572 /*!
2573  * Finds cells whose bounding boxes intersect a given bounding box.
2574  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2575  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2576  *         zMax (if in 3D). 
2577  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2578  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2579  *         extent of the bounding box of cell to produce an addition to this bounding box.
2580  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2581  *         cells. The caller is to delete this array using decrRef() as it is no more
2582  *         needed. 
2583  *  \throw If the coordinates array is not set.
2584  *  \throw If the nodal connectivity of cells is not defined.
2585  *
2586  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2587  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2588  */
2589 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2590 {
2591   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2592   if(getMeshDimension()==-1)
2593     {
2594       elems->pushBackSilent(0);
2595       return elems.retn();
2596     }
2597   int dim=getSpaceDimension();
2598   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2599   const int* conn      = getNodalConnectivity()->getConstPointer();
2600   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2601   const double* coords = getCoords()->getConstPointer();
2602   int nbOfCells=getNumberOfCells();
2603   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2604     {
2605       for (int i=0; i<dim; i++)
2606         {
2607           elem_bb[i*2]=std::numeric_limits<double>::max();
2608           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2609         }
2610
2611       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2612         {
2613           int node= conn[inode];
2614           if(node>=0)//avoid polyhedron separator
2615             {
2616               for (int idim=0; idim<dim; idim++)
2617                 {
2618                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2619                     {
2620                       elem_bb[idim*2] = coords[node*dim+idim] ;
2621                     }
2622                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2623                     {
2624                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2625                     }
2626                 }
2627             }
2628         }
2629       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2630         elems->pushBackSilent(ielem);
2631     }
2632   return elems.retn();
2633 }
2634
2635 /*!
2636  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2637  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2638  * added in 'elems' parameter.
2639  */
2640 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2641 {
2642   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2643   if(getMeshDimension()==-1)
2644     {
2645       elems->pushBackSilent(0);
2646       return elems.retn();
2647     }
2648   int dim=getSpaceDimension();
2649   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2650   const int* conn      = getNodalConnectivity()->getConstPointer();
2651   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2652   const double* coords = getCoords()->getConstPointer();
2653   int nbOfCells=getNumberOfCells();
2654   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2655     {
2656       for (int i=0; i<dim; i++)
2657         {
2658           elem_bb[i*2]=std::numeric_limits<double>::max();
2659           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2660         }
2661
2662       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2663         {
2664           int node= conn[inode];
2665           if(node>=0)//avoid polyhedron separator
2666             {
2667               for (int idim=0; idim<dim; idim++)
2668                 {
2669                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2670                     {
2671                       elem_bb[idim*2] = coords[node*dim+idim] ;
2672                     }
2673                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2674                     {
2675                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2676                     }
2677                 }
2678             }
2679         }
2680       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2681         elems->pushBackSilent(ielem);
2682     }
2683   return elems.retn();
2684 }
2685
2686 /*!
2687  * Returns a type of a cell by its id.
2688  *  \param [in] cellId - the id of the cell of interest.
2689  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2690  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2691  */
2692 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2693 {
2694   const int *ptI=_nodal_connec_index->getConstPointer();
2695   const int *pt=_nodal_connec->getConstPointer();
2696   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2697     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2698   else
2699     {
2700       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2701       throw INTERP_KERNEL::Exception(oss.str().c_str());
2702     }
2703 }
2704
2705 /*!
2706  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2707  * This method does not throw exception if geometric type \a type is not in \a this.
2708  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2709  * The coordinates array is not considered here.
2710  *
2711  * \param [in] type the geometric type
2712  * \return cell ids in this having geometric type \a type.
2713  */
2714 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2715 {
2716   
2717   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2718   ret->alloc(0,1);
2719   checkConnectivityFullyDefined();
2720   int nbCells=getNumberOfCells();
2721   int mdim=getMeshDimension();
2722   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2723   if(mdim!=(int)cm.getDimension())
2724     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2725   const int *ptI=_nodal_connec_index->getConstPointer();
2726   const int *pt=_nodal_connec->getConstPointer();
2727   for(int i=0;i<nbCells;i++)
2728     {
2729       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2730         ret->pushBackSilent(i);
2731     }
2732   return ret.retn();
2733 }
2734
2735 /*!
2736  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2737  */
2738 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2739 {
2740   const int *ptI=_nodal_connec_index->getConstPointer();
2741   const int *pt=_nodal_connec->getConstPointer();
2742   int nbOfCells=getNumberOfCells();
2743   int ret=0;
2744   for(int i=0;i<nbOfCells;i++)
2745     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2746       ret++;
2747   return ret;
2748 }
2749
2750 /*!
2751  * Returns the nodal connectivity of a given cell.
2752  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2753  * all returned node ids can be used in getCoordinatesOfNode().
2754  *  \param [in] cellId - an id of the cell of interest.
2755  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2756  *         cleared before the appending.
2757  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2758  */
2759 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2760 {
2761   const int *ptI=_nodal_connec_index->getConstPointer();
2762   const int *pt=_nodal_connec->getConstPointer();
2763   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2764     if(*w>=0)
2765       conn.push_back(*w);
2766 }
2767
2768 std::string MEDCouplingUMesh::simpleRepr() const
2769 {
2770   static const char msg0[]="No coordinates specified !";
2771   std::ostringstream ret;
2772   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2773   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2774   int tmpp1,tmpp2;
2775   double tt=getTime(tmpp1,tmpp2);
2776   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2777   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2778   if(_mesh_dim>=-1)
2779     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2780   else
2781     { ret << " Mesh dimension has not been set or is invalid !"; }
2782   if(_coords!=0)
2783     {
2784       const int spaceDim=getSpaceDimension();
2785       ret << spaceDim << "\nInfo attached on space dimension : ";
2786       for(int i=0;i<spaceDim;i++)
2787         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2788       ret << "\n";
2789     }
2790   else
2791     ret << msg0 << "\n";
2792   ret << "Number of nodes : ";
2793   if(_coords!=0)
2794     ret << getNumberOfNodes() << "\n";
2795   else
2796     ret << msg0 << "\n";
2797   ret << "Number of cells : ";
2798   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2799     ret << getNumberOfCells() << "\n";
2800   else
2801     ret << "No connectivity specified !" << "\n";
2802   ret << "Cell types present : ";
2803   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2804     {
2805       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2806       ret << cm.getRepr() << " ";
2807     }
2808   ret << "\n";
2809   return ret.str();
2810 }
2811
2812 std::string MEDCouplingUMesh::advancedRepr() const
2813 {
2814   std::ostringstream ret;
2815   ret << simpleRepr();
2816   ret << "\nCoordinates array : \n___________________\n\n";
2817   if(_coords)
2818     _coords->reprWithoutNameStream(ret);
2819   else
2820     ret << "No array set !\n";
2821   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2822   reprConnectivityOfThisLL(ret);
2823   return ret.str();
2824 }
2825
2826 /*!
2827  * This method returns a C++ code that is a dump of \a this.
2828  * This method will throw if this is not fully defined.
2829  */
2830 std::string MEDCouplingUMesh::cppRepr() const
2831 {
2832   static const char coordsName[]="coords";
2833   static const char connName[]="conn";
2834   static const char connIName[]="connI";
2835   checkFullyDefined();
2836   std::ostringstream ret; ret << "// coordinates" << std::endl;
2837   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2838   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2839   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2840   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2841   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2842   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2843   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2844   return ret.str();
2845 }
2846
2847 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2848 {
2849   std::ostringstream ret;
2850   reprConnectivityOfThisLL(ret);
2851   return ret.str();
2852 }
2853
2854 /*!
2855  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2856  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2857  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2858  * some algos).
2859  * 
2860  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2861  * 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
2862  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2863  */
2864 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2865 {
2866   int mdim=getMeshDimension();
2867   if(mdim<0)
2868     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2869   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2870   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2871   bool needToCpyCT=true;
2872   if(!_nodal_connec)
2873     {
2874       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2875       needToCpyCT=false;
2876     }
2877   else
2878     {
2879       tmp1=_nodal_connec;
2880       tmp1->incrRef();
2881     }
2882   if(!_nodal_connec_index)
2883     {
2884       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2885       needToCpyCT=false;
2886     }
2887   else
2888     {
2889       tmp2=_nodal_connec_index;
2890       tmp2->incrRef();
2891     }
2892   ret->setConnectivity(tmp1,tmp2,false);
2893   if(needToCpyCT)
2894     ret->_types=_types;
2895   if(!_coords)
2896     {
2897       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2898       ret->setCoords(coords);
2899     }
2900   else
2901     ret->setCoords(_coords);
2902   return ret.retn();
2903 }
2904
2905 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2906 {
2907   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2908     {
2909       int nbOfCells=getNumberOfCells();
2910       const int *c=_nodal_connec->getConstPointer();
2911       const int *ci=_nodal_connec_index->getConstPointer();
2912       for(int i=0;i<nbOfCells;i++)
2913         {
2914           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2915           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2916           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2917           stream << "\n";
2918         }
2919     }
2920   else
2921     stream << "Connectivity not defined !\n";
2922 }
2923
2924 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2925 {
2926   const int *ptI=_nodal_connec_index->getConstPointer();
2927   const int *pt=_nodal_connec->getConstPointer();
2928   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2929     return ptI[cellId+1]-ptI[cellId]-1;
2930   else
2931     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2932 }
2933
2934 /*!
2935  * Returns types of cells of the specified part of \a this mesh.
2936  * This method avoids computing sub-mesh explicitely to get its types.
2937  *  \param [in] begin - an array of cell ids of interest.
2938  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2939  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2940  *         describing the cell types. 
2941  *  \throw If the coordinates array is not set.
2942  *  \throw If the nodal connectivity of cells is not defined.
2943  *  \sa getAllGeoTypes()
2944  */
2945 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
2946 {
2947   checkFullyDefined();
2948   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2949   const int *conn=_nodal_connec->getConstPointer();
2950   const int *connIndex=_nodal_connec_index->getConstPointer();
2951   for(const int *w=begin;w!=end;w++)
2952     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2953   return ret;
2954 }
2955
2956 /*!
2957  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2958  * a set of types of cells constituting \a this mesh. 
2959  * This method is for advanced users having prepared their connectivity before. For
2960  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2961  *  \param [in] conn - the nodal connectivity array. 
2962  *  \param [in] connIndex - the nodal connectivity index array.
2963  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2964  *         mesh is updated.
2965  */
2966 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2967 {
2968   DataArrayInt::SetArrayIn(conn,_nodal_connec);
2969   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2970   if(isComputingTypes)
2971     computeTypes();
2972   declareAsNew();
2973 }
2974
2975 /*!
2976  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2977  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2978  */
2979 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2980                                                                                  _nodal_connec(0),_nodal_connec_index(0),
2981                                                                                 _types(other._types)
2982 {
2983   if(other._nodal_connec)
2984     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2985   if(other._nodal_connec_index)
2986     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2987 }
2988
2989 MEDCouplingUMesh::~MEDCouplingUMesh()
2990 {
2991   if(_nodal_connec)
2992     _nodal_connec->decrRef();
2993   if(_nodal_connec_index)
2994     _nodal_connec_index->decrRef();
2995 }
2996
2997 /*!
2998  * Recomputes a set of cell types of \a this mesh. For more info see
2999  * \ref MEDCouplingUMeshNodalConnectivity.
3000  */
3001 void MEDCouplingUMesh::computeTypes()
3002 {
3003   if(_nodal_connec && _nodal_connec_index)
3004     {
3005       _types.clear();
3006       const int *conn=_nodal_connec->getConstPointer();
3007       const int *connIndex=_nodal_connec_index->getConstPointer();
3008       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3009       if (nbOfElem > 0)
3010         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3011           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3012     }
3013 }
3014
3015 /*!
3016  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3017  */
3018 void MEDCouplingUMesh::checkFullyDefined() const
3019 {
3020   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3021     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3022 }
3023
3024 /*!
3025  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3026  */
3027 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3028 {
3029   if(!_nodal_connec_index || !_nodal_connec)
3030     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3031 }
3032
3033 /*!
3034  * Returns a number of cells constituting \a this mesh. 
3035  *  \return int - the number of cells in \a this mesh.
3036  *  \throw If the nodal connectivity of cells is not defined.
3037  */
3038 int MEDCouplingUMesh::getNumberOfCells() const
3039
3040   if(_nodal_connec_index)
3041     return _nodal_connec_index->getNumberOfTuples()-1;
3042   else
3043     if(_mesh_dim==-1)
3044       return 1;
3045     else
3046       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3047 }
3048
3049 /*!
3050  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3051  * mesh. For more info see \ref MEDCouplingMeshesPage.
3052  *  \return int - the dimension of \a this mesh.
3053  *  \throw If the mesh dimension is not defined using setMeshDimension().
3054  */
3055 int MEDCouplingUMesh::getMeshDimension() const
3056 {
3057   if(_mesh_dim<-1)
3058     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3059   return _mesh_dim;
3060 }
3061
3062 /*!
3063  * Returns a length of the nodal connectivity array.
3064  * This method is for test reason. Normally the integer returned is not useable by
3065  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3066  *  \return int - the length of the nodal connectivity array.
3067  */
3068 int MEDCouplingUMesh::getMeshLength() const
3069 {
3070   return _nodal_connec->getNbOfElems();
3071 }
3072
3073 /*!
3074  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3075  */
3076 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3077 {
3078   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3079   tinyInfo.push_back(getMeshDimension());
3080   tinyInfo.push_back(getNumberOfCells());
3081   if(_nodal_connec)
3082     tinyInfo.push_back(getMeshLength());
3083   else
3084     tinyInfo.push_back(-1);
3085 }
3086
3087 /*!
3088  * First step of unserialization process.
3089  */
3090 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3091 {
3092   return tinyInfo[6]<=0;
3093 }
3094
3095 /*!
3096  * Second step of serialization process.
3097  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3098  */
3099 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3100 {
3101   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3102   if(tinyInfo[5]!=-1)
3103     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3104 }
3105
3106 /*!
3107  * Third and final step of serialization process.
3108  */
3109 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3110 {
3111   MEDCouplingPointSet::serialize(a1,a2);
3112   if(getMeshDimension()>-1)
3113     {
3114       a1=DataArrayInt::New();
3115       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3116       int *ptA1=a1->getPointer();
3117       const int *conn=getNodalConnectivity()->getConstPointer();
3118       const int *index=getNodalConnectivityIndex()->getConstPointer();
3119       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3120       std::copy(conn,conn+getMeshLength(),ptA1);
3121     }
3122   else
3123     a1=0;
3124 }
3125
3126 /*!
3127  * Second and final unserialization process.
3128  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3129  */
3130 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3131 {
3132   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3133   setMeshDimension(tinyInfo[5]);
3134   if(tinyInfo[7]!=-1)
3135     {
3136       // Connectivity
3137       const int *recvBuffer=a1->getConstPointer();
3138       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3139       myConnecIndex->alloc(tinyInfo[6]+1,1);
3140       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3141       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3142       myConnec->alloc(tinyInfo[7],1);
3143       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3144       setConnectivity(myConnec, myConnecIndex);
3145     }
3146 }
3147
3148 /*!
3149  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3150  * CellIds are given using range specified by a start an end and step.
3151  */
3152 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3153 {
3154   checkFullyDefined();
3155   int ncell=getNumberOfCells();
3156   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3157   ret->_mesh_dim=_mesh_dim;
3158   ret->setCoords(_coords);
3159   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3160   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3161   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3162   int work=start;
3163   const int *conn=_nodal_connec->getConstPointer();
3164   const int *connIndex=_nodal_connec_index->getConstPointer();
3165   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3166     {
3167       if(work>=0 && work<ncell)
3168         {
3169           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3170         }
3171       else
3172         {
3173           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3174           throw INTERP_KERNEL::Exception(oss.str().c_str());
3175         }
3176     }
3177   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3178   int *newConnPtr=newConn->getPointer();
3179   std::set<INTERP_KERNEL::NormalizedCellType> types;
3180   work=start;
3181   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3182     {
3183       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3184       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3185     }
3186   ret->setConnectivity(newConn,newConnI,false);
3187   ret->_types=types;
3188   ret->copyTinyInfoFrom(this);
3189   return ret.retn();
3190 }
3191
3192 /*!
3193  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3194  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3195  * The return newly allocated mesh will share the same coordinates as \a this.
3196  */
3197 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3198 {
3199   checkConnectivityFullyDefined();
3200   int ncell=getNumberOfCells();
3201   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3202   ret->_mesh_dim=_mesh_dim;
3203   ret->setCoords(_coords);
3204   std::size_t nbOfElemsRet=std::distance(begin,end);
3205   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3206   connIndexRet[0]=0;
3207   const int *conn=_nodal_connec->getConstPointer();
3208   const int *connIndex=_nodal_connec_index->getConstPointer();
3209   int newNbring=0;
3210   for(const int *work=begin;work!=end;work++,newNbring++)
3211     {
3212       if(*work>=0 && *work<ncell)
3213         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3214       else
3215         {
3216           free(connIndexRet);
3217           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3218           throw INTERP_KERNEL::Exception(oss.str().c_str());
3219         }
3220     }
3221   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3222   int *connRetWork=connRet;
3223   std::set<INTERP_KERNEL::NormalizedCellType> types;
3224   for(const int *work=begin;work!=end;work++)
3225     {
3226       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3227       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3228     }
3229   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3230   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3231   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3232   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3233   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3234   ret->_types=types;
3235   ret->copyTinyInfoFrom(this);
3236   return ret.retn();
3237 }
3238
3239 /*!
3240  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3241  * mesh.<br>
3242  * For 1D cells, the returned field contains lengths.<br>
3243  * For 2D cells, the returned field contains areas.<br>
3244  * For 3D cells, the returned field contains volumes.
3245  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3246  *         orientation, i.e. the volume is always positive.
3247  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3248  *         and one time . The caller is to delete this field using decrRef() as it is no
3249  *         more needed.
3250  */
3251 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3252 {
3253   std::string name="MeasureOfMesh_";
3254   name+=getName();
3255   int nbelem=getNumberOfCells();
3256   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3257   field->setName(name);
3258   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3259   array->alloc(nbelem,1);
3260   double *area_vol=array->getPointer();
3261   field->setArray(array) ; array=0;
3262   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3263   field->synchronizeTimeWithMesh();
3264   if(getMeshDimension()!=-1)
3265     {
3266       int ipt;
3267       INTERP_KERNEL::NormalizedCellType type;
3268       int dim_space=getSpaceDimension();
3269       const double *coords=getCoords()->getConstPointer();
3270       const int *connec=getNodalConnectivity()->getConstPointer();
3271       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3272       for(int iel=0;iel<nbelem;iel++)
3273         {
3274           ipt=connec_index[iel];
3275           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3276           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);
3277         }
3278       if(isAbs)
3279         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3280     }
3281   else
3282     {
3283       area_vol[0]=std::numeric_limits<double>::max();
3284     }
3285   return field.retn();
3286 }
3287
3288 /*!
3289  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3290  * mesh.<br>
3291  * For 1D cells, the returned array contains lengths.<br>
3292  * For 2D cells, the returned array contains areas.<br>
3293  * For 3D cells, the returned array contains volumes.
3294  * This method avoids building explicitly a part of \a this mesh to perform the work.
3295  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3296  *         orientation, i.e. the volume is always positive.
3297  *  \param [in] begin - an array of cell ids of interest.
3298  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3299  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3300  *          delete this array using decrRef() as it is no more needed.
3301  * 
3302  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3303  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3304  *  \sa getMeasureField()
3305  */
3306 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3307 {
3308   std::string name="PartMeasureOfMesh_";
3309   name+=getName();
3310   int nbelem=(int)std::distance(begin,end);
3311   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3312   array->setName(name);
3313   array->alloc(nbelem,1);
3314   double *area_vol=array->getPointer();
3315   if(getMeshDimension()!=-1)
3316     {
3317       int ipt;
3318       INTERP_KERNEL::NormalizedCellType type;
3319       int dim_space=getSpaceDimension();
3320       const double *coords=getCoords()->getConstPointer();
3321       const int *connec=getNodalConnectivity()->getConstPointer();
3322       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3323       for(const int *iel=begin;iel!=end;iel++)
3324         {
3325           ipt=connec_index[*iel];
3326           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3327           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3328         }
3329       if(isAbs)
3330         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3331     }
3332   else
3333     {
3334       area_vol[0]=std::numeric_limits<double>::max();
3335     }
3336   return array.retn();
3337 }
3338
3339 /*!
3340  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3341  * \a this one. The returned field contains the dual cell volume for each corresponding
3342  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3343  *  the dual mesh in P1 sens of \a this.<br>
3344  * For 1D cells, the returned field contains lengths.<br>
3345  * For 2D cells, the returned field contains areas.<br>
3346  * For 3D cells, the returned field contains volumes.
3347  * This method is useful to check "P1*" conservative interpolators.
3348  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3349  *         orientation, i.e. the volume is always positive.
3350  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3351  *          nodes and one time. The caller is to delete this array using decrRef() as
3352  *          it is no more needed.
3353  */
3354 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3355 {
3356   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3357   std::string name="MeasureOnNodeOfMesh_";
3358   name+=getName();
3359   int nbNodes=getNumberOfNodes();
3360   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3361   double cst=1./((double)getMeshDimension()+1.);
3362   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3363   array->alloc(nbNodes,1);
3364   double *valsToFill=array->getPointer();
3365   std::fill(valsToFill,valsToFill+nbNodes,0.);
3366   const double *values=tmp->getArray()->getConstPointer();
3367   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3369   getReverseNodalConnectivity(da,daInd);
3370   const int *daPtr=da->getConstPointer();
3371   const int *daIPtr=daInd->getConstPointer();
3372   for(int i=0;i<nbNodes;i++)
3373     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3374       valsToFill[i]+=cst*values[*cell];
3375   ret->setMesh(this);
3376   ret->setArray(array);
3377   return ret.retn();
3378 }
3379
3380 /*!
3381  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3382  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3383  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3384  * and are normalized.
3385  * <br> \a this can be either 
3386  * - a  2D mesh in 2D or 3D space or 
3387  * - an 1D mesh in 2D space.
3388  * 
3389  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3390  *          cells and one time. The caller is to delete this field using decrRef() as
3391  *          it is no more needed.
3392  *  \throw If the nodal connectivity of cells is not defined.
3393  *  \throw If the coordinates array is not set.
3394  *  \throw If the mesh dimension is not set.
3395  *  \throw If the mesh and space dimension is not as specified above.
3396  */
3397 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3398 {
3399   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3400     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3401   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3402   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3403   int nbOfCells=getNumberOfCells();
3404   int nbComp=getMeshDimension()+1;
3405   array->alloc(nbOfCells,nbComp);
3406   double *vals=array->getPointer();
3407   const int *connI=_nodal_connec_index->getConstPointer();
3408   const int *conn=_nodal_connec->getConstPointer();
3409   const double *coords=_coords->getConstPointer();
3410   if(getMeshDimension()==2)
3411     {
3412       if(getSpaceDimension()==3)
3413         {
3414           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3415           const double *locPtr=loc->getConstPointer();
3416           for(int i=0;i<nbOfCells;i++,vals+=3)
3417             {
3418               int offset=connI[i];
3419               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3420               double n=INTERP_KERNEL::norm<3>(vals);
3421               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3422             }
3423         }
3424       else
3425         {
3426           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3427           const double *isAbsPtr=isAbs->getArray()->begin();
3428           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3429             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3430         }
3431     }
3432   else//meshdimension==1
3433     {
3434       double tmp[2];
3435       for(int i=0;i<nbOfCells;i++)
3436         {
3437           int offset=connI[i];
3438           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3439           double n=INTERP_KERNEL::norm<2>(tmp);
3440           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3441           *vals++=-tmp[1];
3442           *vals++=tmp[0];
3443         }
3444     }
3445   ret->setArray(array);
3446   ret->setMesh(this);
3447   ret->synchronizeTimeWithSupport();
3448   return ret.retn();
3449 }
3450
3451 /*!
3452  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3453  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3454  * and are normalized.
3455  * <br> \a this can be either 
3456  * - a  2D mesh in 2D or 3D space or 
3457  * - an 1D mesh in 2D space.
3458  * 
3459  * This method avoids building explicitly a part of \a this mesh to perform the work.
3460  *  \param [in] begin - an array of cell ids of interest.
3461  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3462  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3463  *          cells and one time. The caller is to delete this field using decrRef() as
3464  *          it is no more needed.
3465  *  \throw If the nodal connectivity of cells is not defined.
3466  *  \throw If the coordinates array is not set.
3467  *  \throw If the mesh dimension is not set.
3468  *  \throw If the mesh and space dimension is not as specified above.
3469  *  \sa buildOrthogonalField()
3470  *
3471  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3472  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3473  */
3474 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3475 {
3476   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3477     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3478   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3479   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3480   std::size_t nbelems=std::distance(begin,end);
3481   int nbComp=getMeshDimension()+1;
3482   array->alloc((int)nbelems,nbComp);
3483   double *vals=array->getPointer();
3484   const int *connI=_nodal_connec_index->getConstPointer();
3485   const int *conn=_nodal_connec->getConstPointer();
3486   const double *coords=_coords->getConstPointer();
3487   if(getMeshDimension()==2)
3488     {
3489       if(getSpaceDimension()==3)
3490         {
3491           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3492           const double *locPtr=loc->getConstPointer();
3493           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3494             {
3495               int offset=connI[*i];
3496               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3497               double n=INTERP_KERNEL::norm<3>(vals);
3498               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3499             }
3500         }
3501       else
3502         {
3503           for(std::size_t i=0;i<nbelems;i++)
3504             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3505         }
3506     }
3507   else//meshdimension==1
3508     {
3509       double tmp[2];
3510       for(const int *i=begin;i!=end;i++)
3511         {
3512           int offset=connI[*i];
3513           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3514           double n=INTERP_KERNEL::norm<2>(tmp);
3515           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3516           *vals++=-tmp[1];
3517           *vals++=tmp[0];
3518         }
3519     }
3520   ret->setArray(array);
3521   ret->setMesh(this);
3522   ret->synchronizeTimeWithSupport();
3523   return ret.retn();
3524 }
3525
3526 /*!
3527  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3528  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3529  * and are \b not normalized.
3530  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3531  *          cells and one time. The caller is to delete this field using decrRef() as
3532  *          it is no more needed.
3533  *  \throw If the nodal connectivity of cells is not defined.
3534  *  \throw If the coordinates array is not set.
3535  *  \throw If \a this->getMeshDimension() != 1.
3536  *  \throw If \a this mesh includes cells of type other than SEG2.
3537  */
3538 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3539 {
3540    if(getMeshDimension()!=1)
3541     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3542    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3543      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3544    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3545    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3546    int nbOfCells=getNumberOfCells();
3547    int spaceDim=getSpaceDimension();
3548    array->alloc(nbOfCells,spaceDim);
3549    double *pt=array->getPointer();
3550    const double *coo=getCoords()->getConstPointer();
3551    std::vector<int> conn;
3552    conn.reserve(2);
3553    for(int i=0;i<nbOfCells;i++)
3554      {
3555        conn.resize(0);
3556        getNodeIdsOfCell(i,conn);
3557        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3558      }
3559    ret->setArray(array);
3560    ret->setMesh(this);
3561    ret->synchronizeTimeWithSupport();
3562    return ret.retn();   
3563 }
3564
3565 /*!
3566  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3567  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3568  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3569  * from. If a result face is shared by two 3D cells, then the face in included twice in
3570  * the result mesh.
3571  *  \param [in] origin - 3 components of a point defining location of the plane.
3572  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3573  *         must be greater than 1e-6.
3574  *  \param [in] eps - half-thickness of the plane.
3575  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3576  *         producing correspondent 2D cells. The caller is to delete this array
3577  *         using decrRef() as it is no more needed.
3578  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3579  *         not share the node coordinates array with \a this mesh. The caller is to
3580  *         delete this mesh using decrRef() as it is no more needed.  
3581  *  \throw If the coordinates array is not set.
3582  *  \throw If the nodal connectivity of cells is not defined.
3583  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3584  *  \throw If magnitude of \a vec is less than 1e-6.
3585  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3586  *  \throw If \a this includes quadratic cells.
3587  */
3588 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3589 {
3590   checkFullyDefined();
3591   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3592     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3593   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3594   if(candidates->empty())
3595     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3596   std::vector<int> nodes;
3597   DataArrayInt *cellIds1D=0;
3598   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3599   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3600   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3601   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3602   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3603   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3604   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3605   revDesc2=0; revDescIndx2=0;
3606   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3607   revDesc1=0; revDescIndx1=0;
3608   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3609   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3610   //
3611   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3612   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3613     cut3DCurve[*it]=-1;
3614   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3615   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3616   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3617                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3618                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3619   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3620   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3621   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3622   if(cellIds2->empty())
3623     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3624   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3625   ret->setCoords(mDesc1->getCoords());
3626   ret->setConnectivity(conn,connI,true);
3627   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3628   return ret.retn();
3629 }
3630
3631 /*!
3632  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3633 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
3634 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3635 the result mesh.
3636  *  \param [in] origin - 3 components of a point defining location of the plane.
3637  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3638  *         must be greater than 1e-6.
3639  *  \param [in] eps - half-thickness of the plane.
3640  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3641  *         producing correspondent segments. The caller is to delete this array
3642  *         using decrRef() as it is no more needed.
3643  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3644  *         mesh in 3D space. This mesh does not share the node coordinates array with
3645  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3646  *         no more needed. 
3647  *  \throw If the coordinates array is not set.
3648  *  \throw If the nodal connectivity of cells is not defined.
3649  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3650  *  \throw If magnitude of \a vec is less than 1e-6.
3651  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3652  *  \throw If \a this includes quadratic cells.
3653  */
3654 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3655 {
3656   checkFullyDefined();
3657   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3658     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3659   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3660   if(candidates->empty())
3661     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3662   std::vector<int> nodes;
3663   DataArrayInt *cellIds1D=0;
3664   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3665   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3666   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3667   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3668   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3669   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3670   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3671   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3672   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3673   //
3674   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3675   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3676     cut3DCurve[*it]=-1;
3677   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3678   int ncellsSub=subMesh->getNumberOfCells();
3679   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3680   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3681                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3682                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3683   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3684   conn->alloc(0,1);
3685   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3686   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3687   for(int i=0;i<ncellsSub;i++)
3688     {
3689       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3690         {
3691           if(cut3DSurf[i].first!=-2)
3692             {
3693               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3694               connI->pushBackSilent(conn->getNumberOfTuples());
3695               cellIds2->pushBackSilent(i);
3696             }
3697           else
3698             {
3699               int cellId3DSurf=cut3DSurf[i].second;
3700               int offset=nodalI[cellId3DSurf]+1;
3701               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3702               for(int j=0;j<nbOfEdges;j++)
3703                 {
3704                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3705                   connI->pushBackSilent(conn->getNumberOfTuples());
3706                   cellIds2->pushBackSilent(cellId3DSurf);
3707                 }
3708             }
3709         }
3710     }
3711   if(cellIds2->empty())
3712     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3713   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3714   ret->setCoords(mDesc1->getCoords());
3715   ret->setConnectivity(conn,connI,true);
3716   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3717   return ret.retn();
3718 }
3719
3720 /*!
3721  * Finds cells whose bounding boxes intersect a given plane.
3722  *  \param [in] origin - 3 components of a point defining location of the plane.
3723  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3724  *         must be greater than 1e-6.
3725  *  \param [in] eps - half-thickness of the plane.
3726  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3727  *         cells. The caller is to delete this array using decrRef() as it is no more
3728  *         needed.
3729  *  \throw If the coordinates array is not set.
3730  *  \throw If the nodal connectivity of cells is not defined.
3731  *  \throw If \a this->getSpaceDimension() != 3.
3732  *  \throw If magnitude of \a vec is less than 1e-6.
3733  *  \sa buildSlice3D()
3734  */
3735 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3736 {
3737   checkFullyDefined();
3738   if(getSpaceDimension()!=3)
3739     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3740   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3741   if(normm<1e-6)
3742     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3743   double vec2[3];
3744   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3745   double angle=acos(vec[2]/normm);
3746   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3747   double bbox[6];
3748   if(angle>eps)
3749     {
3750       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3751       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3752       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3753       mw->setCoords(coo);
3754       mw->getBoundingBox(bbox);
3755       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3756       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3757     }
3758   else
3759     {
3760       getBoundingBox(bbox);
3761       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3762       cellIds=getCellsInBoundingBox(bbox,eps);
3763     }
3764   return cellIds.retn();
3765 }
3766
3767 /*!
3768  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3769  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3770  * No consideration of coordinate is done by this method.
3771  * 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)
3772  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3773  */
3774 bool MEDCouplingUMesh::isContiguous1D() const
3775 {
3776   if(getMeshDimension()!=1)
3777     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3778   int nbCells=getNumberOfCells();
3779   if(nbCells<1)
3780     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3781   const int *connI=_nodal_connec_index->getConstPointer();
3782   const int *conn=_nodal_connec->getConstPointer();
3783   int ref=conn[connI[0]+2];
3784   for(int i=1;i<nbCells;i++)
3785     {
3786       if(conn[connI[i]+1]!=ref)
3787         return false;
3788       ref=conn[connI[i]+2];
3789     }
3790   return true;
3791 }
3792
3793 /*!
3794  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3795  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3796  * \param pt reference point of the line
3797  * \param v normalized director vector of the line
3798  * \param eps max precision before throwing an exception
3799  * \param res output of size this->getNumberOfCells
3800  */
3801 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3802 {
3803   if(getMeshDimension()!=1)
3804     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3805    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3806      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3807    if(getSpaceDimension()!=3)
3808      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3809    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3810    const double *fPtr=f->getArray()->getConstPointer();
3811    double tmp[3];
3812    for(int i=0;i<getNumberOfCells();i++)
3813      {
3814        const double *tmp1=fPtr+3*i;
3815        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3816        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3817        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3818        double n1=INTERP_KERNEL::norm<3>(tmp);
3819        n1/=INTERP_KERNEL::norm<3>(tmp1);
3820        if(n1>eps)
3821          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3822      }
3823    const double *coo=getCoords()->getConstPointer();
3824    for(int i=0;i<getNumberOfNodes();i++)
3825      {
3826        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3827        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3828        res[i]=std::accumulate(tmp,tmp+3,0.);
3829      }
3830 }
3831
3832 /*!
3833  * 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. 
3834  * \a this is expected to be a mesh so that its space dimension is equal to its
3835  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3836  * 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).
3837  
3838  * 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
3839  * 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).
3840  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3841  *
3842  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3843  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3844  *
3845  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3846  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3847  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3848  * \return the positive value of the distance.
3849  * \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
3850  * dimension - 1.
3851  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3852  */
3853 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3854 {
3855   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3856   if(meshDim!=spaceDim-1)
3857     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3858   if(meshDim!=2 && meshDim!=1)
3859     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3860   checkFullyDefined();
3861   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3862     { 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()); }
3863   DataArrayInt *ret1=0;
3864   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3865   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3866   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3867   cellId=*ret1Safe->begin();
3868   return *ret0->begin();
3869 }
3870
3871 /*!
3872  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3873  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3874  * 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
3875  * 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).
3876  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3877  * 
3878  * \a this is expected to be a mesh so that its space dimension is equal to its
3879  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3880  * 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).
3881  *
3882  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3883  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3884  *
3885  * \param [in] pts the list of points in which each tuple represents a point
3886  * \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.
3887  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3888  * \throw if number of components of \a pts is not equal to the space dimension.
3889  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3890  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3891  */
3892 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3893 {
3894   if(!pts)
3895     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3896   pts->checkAllocated();
3897   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3898   if(meshDim!=spaceDim-1)
3899     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3900   if(meshDim!=2 && meshDim!=1)
3901     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3902   if(pts->getNumberOfComponents()!=spaceDim)
3903     {
3904       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3905       throw INTERP_KERNEL::Exception(oss.str().c_str());
3906     }
3907   checkFullyDefined();
3908   int nbCells=getNumberOfCells();
3909   if(nbCells==0)
3910     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3911   int nbOfPts=pts->getNumberOfTuples();
3912   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3913   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3914   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3915   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3916   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3917   const double *bbox(bboxArr->begin());
3918   switch(spaceDim)
3919     {
3920     case 3:
3921       {
3922         BBTreeDst<3> myTree(bbox,0,0,nbCells);
3923         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3924           {
3925             double x=std::numeric_limits<double>::max();
3926             std::vector<int> elems;
3927             myTree.getMinDistanceOfMax(ptsPtr,x);
3928             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3929             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3930           }
3931         break;
3932       }
3933     case 2:
3934       {
3935         BBTreeDst<2> myTree(bbox,0,0,nbCells);
3936         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3937           {
3938             double x=std::numeric_limits<double>::max();
3939             std::vector<int> elems;
3940             myTree.getMinDistanceOfMax(ptsPtr,x);
3941             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3942             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3943           }
3944         break;
3945       }
3946     default:
3947       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3948     }
3949   cellIds=ret1.retn();
3950   return ret0.retn();
3951 }
3952
3953 /*!
3954  * \param [in] pt the start pointer (included) of the coordinates of the point
3955  * \param [in] cellIdsBg the start pointer (included) of cellIds
3956  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3957  * \param [in] nc nodal connectivity
3958  * \param [in] ncI nodal connectivity index
3959  * \param [in,out] ret0 the min distance between \a this and the external input point
3960  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3961  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3962  */
3963 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)
3964 {
3965   cellId=-1;
3966   ret0=std::numeric_limits<double>::max();
3967   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3968     {
3969       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3970         {
3971         case INTERP_KERNEL::NORM_TRI3:
3972           {
3973             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3974             if(tmp<ret0)
3975               { ret0=tmp; cellId=*zeCell; }
3976             break;
3977           }
3978         case INTERP_KERNEL::NORM_QUAD4:
3979         case INTERP_KERNEL::NORM_POLYGON:
3980           {
3981             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3982             if(tmp<ret0)
3983               { ret0=tmp; cellId=*zeCell; }
3984             break;
3985           }
3986         default:
3987           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3988         }
3989     }
3990 }
3991
3992 /*!
3993  * \param [in] pt the start pointer (included) of the coordinates of the point
3994  * \param [in] cellIdsBg the start pointer (included) of cellIds
3995  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3996  * \param [in] nc nodal connectivity
3997  * \param [in] ncI nodal connectivity index
3998  * \param [in,out] ret0 the min distance between \a this and the external input point
3999  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4000  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4001  */
4002 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)
4003 {
4004   cellId=-1;
4005   ret0=std::numeric_limits<double>::max();
4006   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4007     {
4008        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4009         {
4010         case INTERP_KERNEL::NORM_SEG2:
4011           {
4012             std::size_t uselessEntry=0;
4013             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4014             tmp=sqrt(tmp);
4015             if(tmp<ret0)
4016               { ret0=tmp; cellId=*zeCell; }
4017             break;
4018           }
4019         default:
4020           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4021         }
4022     }
4023 }
4024
4025 /*!
4026  * Finds cells in contact with a ball (i.e. a point with precision). 
4027  * 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.
4028  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4029  *
4030  * \warning This method is suitable if the caller intends to evaluate only one
4031  *          point, for more points getCellsContainingPoints() is recommended as it is
4032  *          faster. 
4033  *  \param [in] pos - array of coordinates of the ball central point.
4034  *  \param [in] eps - ball radius.
4035  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4036  *         if there are no such cells.
4037  *  \throw If the coordinates array is not set.
4038  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4039  */
4040 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4041 {
4042   std::vector<int> elts;
4043   getCellsContainingPoint(pos,eps,elts);
4044   if(elts.empty())
4045     return -1;
4046   return elts.front();
4047 }
4048
4049 /*!
4050  * Finds cells in contact with a ball (i.e. a point with precision).
4051  * 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.
4052  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4053  * \warning This method is suitable if the caller intends to evaluate only one
4054  *          point, for more points getCellsContainingPoints() is recommended as it is
4055  *          faster. 
4056  *  \param [in] pos - array of coordinates of the ball central point.
4057  *  \param [in] eps - ball radius.
4058  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4059  *         before inserting ids.
4060  *  \throw If the coordinates array is not set.
4061  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4062  *
4063  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4064  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4065  */
4066 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4067 {
4068   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4069   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4070   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4071 }
4072
4073 /// @cond INTERNAL
4074
4075 namespace ParaMEDMEM
4076 {
4077   template<const int SPACEDIMM>
4078   class DummyClsMCUG
4079   {
4080   public:
4081     static const int MY_SPACEDIM=SPACEDIMM;
4082     static const int MY_MESHDIM=8;
4083     typedef int MyConnType;
4084     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4085     // begin
4086     // useless, but for windows compilation ...
4087     const double* getCoordinatesPtr() const { return 0; }
4088     const int* getConnectivityPtr() const { return 0; }
4089     const int* getConnectivityIndexPtr() const { return 0; }
4090     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4091     // end
4092   };
4093
4094   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4095   {
4096     INTERP_KERNEL::Edge *ret=0;
4097     switch(typ)
4098       {
4099       case INTERP_KERNEL::NORM_SEG2:
4100         {
4101           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4102           break;
4103         }
4104       case INTERP_KERNEL::NORM_SEG3:
4105         {
4106           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4107           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4108           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4109           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4110           bool colinearity=inters.areColinears();
4111           delete e1; delete e2;
4112           if(colinearity)
4113             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4114           else
4115             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4116           mapp2[bg[2]].second=false;
4117           break;
4118         }
4119       default:
4120         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4121       }
4122     return ret;
4123   }
4124
4125   /*!
4126    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4127    * the global mesh 'mDesc'.
4128    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4129    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4130    */
4131   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4132       std::map<INTERP_KERNEL::Node *,int>& mapp)
4133       throw(INTERP_KERNEL::Exception)
4134   {
4135     mapp.clear();
4136     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.
4137     const double *coo=mDesc->getCoords()->getConstPointer();
4138     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4139     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4140     std::set<int> s;
4141     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4142       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4143     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4144       {
4145         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4146         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4147       }
4148     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4149     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4150       {
4151         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4152         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4153       }
4154     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4155       {
4156         if((*it2).second.second)
4157           mapp[(*it2).second.first]=(*it2).first;
4158         ((*it2).second.first)->decrRef();
4159       }
4160     return ret;
4161   }
4162
4163   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4164   {
4165     if(nodeId>=offset2)
4166       {
4167         int locId=nodeId-offset2;
4168         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4169       }
4170     if(nodeId>=offset1)
4171       {
4172         int locId=nodeId-offset1;
4173         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4174       }
4175     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4176   }
4177
4178   /**
4179    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4180    */
4181   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4182                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4183                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4184   {
4185     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4186       {
4187         int eltId1=abs(*desc1)-1;
4188         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4189           {
4190             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4191             if(it==mappRev.end())
4192               {
4193                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4194                 mapp[node]=*it1;
4195                 mappRev[*it1]=node;
4196               }
4197           }
4198       }
4199   }
4200 }
4201
4202 /// @endcond
4203
4204 template<int SPACEDIM>
4205 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4206                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4207 {
4208   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4209   int *eltsIndexPtr(eltsIndex->getPointer());
4210   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4211   const double *bbox(bboxArr->begin());
4212   int nbOfCells=getNumberOfCells();
4213   const int *conn=_nodal_connec->getConstPointer();
4214   const int *connI=_nodal_connec_index->getConstPointer();
4215   double bb[2*SPACEDIM];
4216   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4217   for(int i=0;i<nbOfPoints;i++)
4218     {
4219       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4220       for(int j=0;j<SPACEDIM;j++)
4221         {
4222           bb[2*j]=pos[SPACEDIM*i+j];
4223           bb[2*j+1]=pos[SPACEDIM*i+j];
4224         }
4225       std::vector<int> candidates;
4226       myTree.getIntersectingElems(bb,candidates);
4227       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4228         {
4229           int sz(connI[(*iter)+1]-connI[*iter]-1);
4230           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4231           bool status(false);
4232           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4233             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4234           else
4235             {
4236               if(SPACEDIM!=2)
4237                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4238               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4239               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4240               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4241               INTERP_KERNEL::QuadraticPolygon *pol(0);
4242               for(int j=0;j<sz;j++)
4243                 {
4244                   int nodeId(conn[connI[*iter]+1+j]);
4245                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4246                 }
4247               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4248                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4249               else
4250                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4251               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4252               double a(0.),b(0.),c(0.);
4253               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4254               status=pol->isInOrOut2(n);
4255               delete pol; n->decrRef();
4256             }
4257           if(status)
4258             {
4259               eltsIndexPtr[i+1]++;
4260               elts->pushBackSilent(*iter);
4261             }
4262         }
4263     }
4264 }
4265 /*!
4266  * Finds cells in contact with several balls (i.e. points with precision).
4267  * This method is an extension of getCellContainingPoint() and
4268  * getCellsContainingPoint() for the case of multiple points.
4269  * 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.
4270  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4271  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4272  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4273  *         this->getSpaceDimension() * \a nbOfPoints 
4274  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4275  *  \param [in] eps - radius of balls (i.e. the precision).
4276  *  \param [out] elts - vector returning ids of found cells.
4277  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4278  *         dividing cell ids in \a elts into groups each referring to one
4279  *         point. Its every element (except the last one) is an index pointing to the
4280  *         first id of a group of cells. For example cells in contact with the *i*-th
4281  *         point are described by following range of indices:
4282  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4283  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4284  *         Number of cells in contact with the *i*-th point is
4285  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4286  *  \throw If the coordinates array is not set.
4287  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4288  *
4289  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4290  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4291  */
4292 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4293                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4294 {
4295   int spaceDim=getSpaceDimension();
4296   int mDim=getMeshDimension();
4297   if(spaceDim==3)
4298     {
4299       if(mDim==3)
4300         {
4301           const double *coords=_coords->getConstPointer();
4302           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4303         }
4304       /*else if(mDim==2)
4305         {
4306           
4307         }*/
4308       else
4309         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4310     }
4311   else if(spaceDim==2)
4312     {
4313       if(mDim==2)
4314         {
4315           const double *coords=_coords->getConstPointer();
4316           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4317         }
4318       else
4319         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4320     }
4321   else if(spaceDim==1)
4322     {
4323       if(mDim==1)
4324         {
4325           const double *coords=_coords->getConstPointer();
4326           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4327         }
4328       else
4329         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4330     }
4331   else
4332     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4333 }
4334
4335 /*!
4336  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4337  * least two its edges intersect each other anywhere except their extremities. An
4338  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4339  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4340  *         cleared before filling in.
4341  *  \param [in] eps - precision.
4342  *  \throw If \a this->getMeshDimension() != 2.
4343  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4344  */
4345 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4346 {
4347   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4348   if(getMeshDimension()!=2)
4349     throw INTERP_KERNEL::Exception(msg);
4350   int spaceDim=getSpaceDimension();
4351   if(spaceDim!=2 && spaceDim!=3)
4352     throw INTERP_KERNEL::Exception(msg);
4353   const int *conn=_nodal_connec->getConstPointer();
4354   const int *connI=_nodal_connec_index->getConstPointer();
4355   int nbOfCells=getNumberOfCells();
4356   std::vector<double> cell2DinS2;
4357   for(int i=0;i<nbOfCells;i++)
4358     {
4359       int offset=connI[i];
4360       int nbOfNodesForCell=connI[i+1]-offset-1;
4361       if(nbOfNodesForCell<=3)
4362         continue;
4363       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4364       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4365       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4366         cells.push_back(i);
4367       cell2DinS2.clear();
4368     }
4369 }
4370
4371 /*!
4372  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4373  *
4374  * 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.
4375  * 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.
4376  * 
4377  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4378  * This convex envelop is computed using Jarvis march algorithm.
4379  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4380  * 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)
4381  * 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.
4382  *
4383  * \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.
4384  */
4385 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4386 {
4387   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4388     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4389   checkFullyDefined();
4390   const double *coords=getCoords()->getConstPointer();
4391   int nbOfCells=getNumberOfCells();
4392   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4393   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4394   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4395   int *workIndexOut=nodalConnecIndexOut->getPointer();
4396   *workIndexOut=0;
4397   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4398   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4399   std::set<INTERP_KERNEL::NormalizedCellType> types;
4400   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4401   isChanged->alloc(0,1);
4402   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4403     {
4404       int pos=nodalConnecOut->getNumberOfTuples();
4405       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4406         isChanged->pushBackSilent(i);
4407       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4408       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4409     }
4410   if(isChanged->empty())
4411     return 0;
4412   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4413   _types=types;
4414   return isChanged.retn();
4415 }
4416
4417 /*!
4418  * This method is \b NOT const because it can modify \a this.
4419  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4420  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4421  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4422  * \b 1 for translation and rotation around point of 'mesh1D'.
4423  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4424  */
4425 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4426 {
4427   checkFullyDefined();
4428   mesh1D->checkFullyDefined();
4429   if(!mesh1D->isContiguous1D())
4430     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4431   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4432     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4433   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4434     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4435   if(mesh1D->getMeshDimension()!=1)
4436     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4437   bool isQuad=false;
4438   if(isPresenceOfQuadratic())
4439     {
4440       if(mesh1D->isFullyQuadratic())
4441         isQuad=true;
4442       else
4443         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4444     }
4445   zipCoords();
4446   int oldNbOfNodes=getNumberOfNodes();
4447   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4448   switch(policy)
4449     {
4450     case 0:
4451       {
4452         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4453         break;
4454       }
4455     case 1:
4456       {
4457         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4458         break;
4459       }
4460     default:
4461       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4462     }
4463   setCoords(newCoords);
4464   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4465   updateTime();
4466   return ret.retn();
4467 }
4468
4469 /*!
4470  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4471  * If it is not the case an exception will be thrown.
4472  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4473  * intersection of plane defined by ('origin','vec').
4474  * This method has one in/out parameter : 'cut3DCurve'.
4475  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4476  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4477  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4478  * This method will throw an exception if \a this contains a non linear segment.
4479  */
4480 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4481 {
4482   checkFullyDefined();
4483   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4484     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4485   int ncells=getNumberOfCells();
4486   int nnodes=getNumberOfNodes();
4487   double vec2[3],vec3[3],vec4[3];
4488   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4489   if(normm<1e-6)
4490     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4491   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4492   const int *conn=_nodal_connec->getConstPointer();
4493   const int *connI=_nodal_connec_index->getConstPointer();
4494   const double *coo=_coords->getConstPointer();
4495   std::vector<double> addCoo;
4496   for(int i=0;i<ncells;i++)
4497     {
4498       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4499         {
4500           if(cut3DCurve[i]==-2)
4501             {
4502               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4503               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];
4504               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4505               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4506               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4507                 {
4508                   const double *st2=coo+3*st;
4509                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4510                   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]));
4511                   if(pos>eps && pos<1-eps)
4512                     {
4513                       int nNode=((int)addCoo.size())/3;
4514                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4515                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4516                       cut3DCurve[i]=nnodes+nNode;
4517                     }
4518                 }
4519             }
4520         }
4521       else
4522         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4523     }
4524   if(!addCoo.empty())
4525     {
4526       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4527       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4528       coo2->alloc(newNbOfNodes,3);
4529       double *tmp=coo2->getPointer();
4530       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4531       std::copy(addCoo.begin(),addCoo.end(),tmp);
4532       DataArrayDouble::SetArrayIn(coo2,_coords);
4533     }
4534 }
4535
4536 /*!
4537  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4538  * \param mesh1D is the input 1D mesh used for translation computation.
4539  * \return newCoords new coords filled by this method. 
4540  */
4541 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4542 {
4543   int oldNbOfNodes=getNumberOfNodes();
4544   int nbOf1DCells=mesh1D->getNumberOfCells();
4545   int spaceDim=getSpaceDimension();
4546   DataArrayDouble *ret=DataArrayDouble::New();
4547   std::vector<bool> isQuads;
4548   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4549   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4550   double *retPtr=ret->getPointer();
4551   const double *coords=getCoords()->getConstPointer();
4552   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4553   std::vector<int> v;
4554   std::vector<double> c;
4555   double vec[3];
4556   v.reserve(3);
4557   c.reserve(6);
4558   for(int i=0;i<nbOf1DCells;i++)
4559     {
4560       v.resize(0);
4561       mesh1D->getNodeIdsOfCell(i,v);
4562       c.resize(0);
4563       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4564       mesh1D->getCoordinatesOfNode(v[0],c);
4565       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4566       for(int j=0;j<oldNbOfNodes;j++)
4567         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4568       if(isQuad)
4569         {
4570           c.resize(0);
4571           mesh1D->getCoordinatesOfNode(v[1],c);
4572           mesh1D->getCoordinatesOfNode(v[0],c);
4573           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4574           for(int j=0;j<oldNbOfNodes;j++)
4575             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4576         }
4577     }
4578   ret->copyStringInfoFrom(*getCoords());
4579   return ret;
4580 }
4581
4582 /*!
4583  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4584  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4585  * \return newCoords new coords filled by this method. 
4586  */
4587 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4588 {
4589   if(mesh1D->getSpaceDimension()==2)
4590     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4591   if(mesh1D->getSpaceDimension()==3)
4592     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4593   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4594 }
4595
4596 /*!
4597  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4598  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4599  * \return newCoords new coords filled by this method. 
4600  */
4601 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4602 {
4603   if(isQuad)
4604     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4605   int oldNbOfNodes=getNumberOfNodes();
4606   int nbOf1DCells=mesh1D->getNumberOfCells();
4607   if(nbOf1DCells<2)
4608     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4609   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4610   int nbOfLevsInVec=nbOf1DCells+1;
4611   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4612   double *retPtr=ret->getPointer();
4613   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4614   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4615   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4616   tmp->setCoords(tmp2);
4617   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4618   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4619   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4620   for(int i=1;i<nbOfLevsInVec;i++)
4621     {
4622       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4623       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4624       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4625       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4626       tmp->translate(vec);
4627       double tmp3[2],radius,alpha,alpha0;
4628       const double *p0=i+1<nbOfLevsInVec?begin:third;
4629       const double *p1=i+1<nbOfLevsInVec?end:begin;
4630       const double *p2=i+1<nbOfLevsInVec?third:end;
4631       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4632       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]);
4633       double angle=acos(cosangle/(radius*radius));
4634       tmp->rotate(end,0,angle);
4635       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4636     }
4637   return ret.retn();
4638 }
4639
4640 /*!
4641  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4642  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4643  * \return newCoords new coords filled by this method. 
4644  */
4645 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4646 {
4647   if(isQuad)
4648     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4649   int oldNbOfNodes=getNumberOfNodes();
4650   int nbOf1DCells=mesh1D->getNumberOfCells();
4651   if(nbOf1DCells<2)
4652     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4653   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4654   int nbOfLevsInVec=nbOf1DCells+1;
4655   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4656   double *retPtr=ret->getPointer();
4657   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4658   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4659   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4660   tmp->setCoords(tmp2);
4661   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4662   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4663   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4664   for(int i=1;i<nbOfLevsInVec;i++)
4665     {
4666       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4667       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4668       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4669       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4670       tmp->translate(vec);
4671       double tmp3[2],radius,alpha,alpha0;
4672       const double *p0=i+1<nbOfLevsInVec?begin:third;
4673       const double *p1=i+1<nbOfLevsInVec?end:begin;
4674       const double *p2=i+1<nbOfLevsInVec?third:end;
4675       double vecPlane[3]={
4676         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4677         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4678         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4679       };
4680       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4681       if(norm>1.e-7)
4682         {
4683           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4684           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4685           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4686           double s2=norm2;
4687           double c2=cos(asin(s2));
4688           double m[3][3]={
4689             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4690             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4691             {-vec2[1]*s2, vec2[0]*s2, c2}
4692           };
4693           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]};
4694           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]};
4695           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]};
4696           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4697           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]);
4698           double angle=acos(cosangle/(radius*radius));
4699           tmp->rotate(end,vecPlane,angle);
4700           
4701         }
4702       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4703     }
4704   return ret.retn();
4705 }
4706
4707 /*!
4708  * This method is private because not easy to use for end user. This method is const contrary to
4709  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4710  * the coords sorted slice by slice.
4711  * \param isQuad specifies presence of quadratic cells.
4712  */
4713 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4714 {
4715   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4716   int nbOf2DCells=getNumberOfCells();
4717   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4718   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4719   const int *conn=_nodal_connec->getConstPointer();
4720   const int *connI=_nodal_connec_index->getConstPointer();
4721   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4722   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4723   newConnI->alloc(nbOf3DCells+1,1);
4724   int *newConnIPtr=newConnI->getPointer();
4725   *newConnIPtr++=0;
4726   std::vector<int> newc;
4727   for(int j=0;j<nbOf2DCells;j++)
4728     {
4729       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4730       *newConnIPtr++=(int)newc.size();
4731     }
4732   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4733   int *newConnPtr=newConn->getPointer();
4734   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4735   newConnIPtr=newConnI->getPointer();
4736   for(int iz=0;iz<nbOf1DCells;iz++)
4737     {
4738       if(iz!=0)
4739         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4740       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4741         {
4742           int icell=(int)(iter-newc.begin());
4743           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4744             {
4745               if(*iter!=-1)
4746                 *newConnPtr=(*iter)+iz*deltaPerLev;
4747               else
4748                 *newConnPtr=-1;
4749             }
4750           else
4751             *newConnPtr=(*iter);
4752         }
4753     }
4754   ret->setConnectivity(newConn,newConnI,true);
4755   ret->setCoords(getCoords());
4756   return ret;
4757 }
4758
4759 /*!
4760  * Checks if \a this mesh is constituted by only quadratic cells.
4761  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4762  *  \throw If the coordinates array is not set.
4763  *  \throw If the nodal connectivity of cells is not defined.
4764  */
4765 bool MEDCouplingUMesh::isFullyQuadratic() const
4766 {
4767   checkFullyDefined();
4768   bool ret=true;
4769   int nbOfCells=getNumberOfCells();
4770   for(int i=0;i<nbOfCells && ret;i++)
4771     {
4772       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4773       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4774       ret=cm.isQuadratic();
4775     }
4776   return ret;
4777 }
4778
4779 /*!
4780  * Checks if \a this mesh includes any quadratic cell.
4781  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4782  *  \throw If the coordinates array is not set.
4783  *  \throw If the nodal connectivity of cells is not defined.
4784  */
4785 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4786 {
4787   checkFullyDefined();
4788   bool ret=false;
4789   int nbOfCells=getNumberOfCells();
4790   for(int i=0;i<nbOfCells && !ret;i++)
4791     {
4792       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4793       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4794       ret=cm.isQuadratic();
4795     }
4796   return ret;
4797 }
4798
4799 /*!
4800  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4801  * this mesh, it remains unchanged.
4802  *  \throw If the coordinates array is not set.
4803  *  \throw If the nodal connectivity of cells is not defined.
4804  */
4805 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4806 {
4807   checkFullyDefined();
4808   int nbOfCells=getNumberOfCells();
4809   int delta=0;
4810   const int *iciptr=_nodal_connec_index->getConstPointer();
4811   for(int i=0;i<nbOfCells;i++)
4812     {
4813       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4814       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4815       if(cm.isQuadratic())
4816         {
4817           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4818           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4819           if(!cml.isDynamic())
4820             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4821           else
4822             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4823         }
4824     }
4825   if(delta==0)
4826     return ;
4827   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4828   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4829   const int *icptr=_nodal_connec->getConstPointer();
4830   newConn->alloc(getMeshLength()-delta,1);
4831   newConnI->alloc(nbOfCells+1,1);
4832   int *ocptr=newConn->getPointer();
4833   int *ociptr=newConnI->getPointer();
4834   *ociptr=0;
4835   _types.clear();
4836   for(int i=0;i<nbOfCells;i++,ociptr++)
4837     {
4838       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4839       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4840       if(!cm.isQuadratic())
4841         {
4842           _types.insert(type);
4843           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4844           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4845         }
4846       else
4847         {
4848           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4849           _types.insert(typel);
4850           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4851           int newNbOfNodes=cml.getNumberOfNodes();
4852           if(cml.isDynamic())
4853             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4854           *ocptr++=(int)typel;
4855           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4856           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4857         }
4858     }
4859   setConnectivity(newConn,newConnI,false);
4860 }
4861
4862 /*!
4863  * This method converts all linear cell in \a this to quadratic one.
4864  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4865  * 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)
4866  * 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.
4867  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4868  * end of the existing coordinates.
4869  * 
4870  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4871  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4872  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4873  * 
4874  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4875  *
4876  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4877  */
4878 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4879 {
4880   DataArrayInt *conn=0,*connI=0;
4881   DataArrayDouble *coords=0;
4882   std::set<INTERP_KERNEL::NormalizedCellType> types;
4883   checkFullyDefined();
4884   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4885   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4886   int meshDim=getMeshDimension();
4887   switch(conversionType)
4888     {
4889     case 0:
4890       switch(meshDim)
4891         {
4892         case 1:
4893           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4894           connSafe=conn; connISafe=connI; coordsSafe=coords;
4895           break;
4896         case 2:
4897           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4898           connSafe=conn; connISafe=connI; coordsSafe=coords;
4899           break;
4900         case 3:
4901           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4902           connSafe=conn; connISafe=connI; coordsSafe=coords;
4903           break;
4904         default:
4905           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4906         }
4907       break;
4908     case 1:
4909       {
4910         switch(meshDim)
4911         {
4912         case 1:
4913           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4914           connSafe=conn; connISafe=connI; coordsSafe=coords;
4915           break;
4916         case 2:
4917           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4918           connSafe=conn; connISafe=connI; coordsSafe=coords;
4919           break;
4920         case 3:
4921           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4922           connSafe=conn; connISafe=connI; coordsSafe=coords;
4923           break;
4924         default:
4925           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4926         }
4927         break;
4928       }
4929     default:
4930       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4931     }
4932   setConnectivity(connSafe,connISafe,false);
4933   _types=types;
4934   setCoords(coordsSafe);
4935   return ret.retn();
4936 }
4937
4938 /*!
4939  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4940  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4941  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4942  */
4943 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
4944 {
4945   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4946   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4947   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4948   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4949   int nbOfCells=getNumberOfCells();
4950   int nbOfNodes=getNumberOfNodes();
4951   const int *cPtr=_nodal_connec->getConstPointer();
4952   const int *icPtr=_nodal_connec_index->getConstPointer();
4953   int lastVal=0,offset=nbOfNodes;
4954   for(int i=0;i<nbOfCells;i++,icPtr++)
4955     {
4956       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4957       if(type==INTERP_KERNEL::NORM_SEG2)
4958         {
4959           types.insert(INTERP_KERNEL::NORM_SEG3);
4960           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4961           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4962           newConn->pushBackSilent(offset++);
4963           lastVal+=4;
4964           newConnI->pushBackSilent(lastVal);
4965           ret->pushBackSilent(i);
4966         }
4967       else
4968         {
4969           types.insert(type);
4970           lastVal+=(icPtr[1]-icPtr[0]);
4971           newConnI->pushBackSilent(lastVal);
4972           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4973         }
4974     }
4975   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4976   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4977   return ret.retn();
4978 }
4979
4980 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
4981 {
4982   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4984   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4985   //
4986   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4987   DataArrayInt *conn1D=0,*conn1DI=0;
4988   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4989   DataArrayDouble *coordsTmp=0;
4990   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4991   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4992   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4993   const int *c1DPtr=conn1D->begin();
4994   const int *c1DIPtr=conn1DI->begin();
4995   int nbOfCells=getNumberOfCells();
4996   const int *cPtr=_nodal_connec->getConstPointer();
4997   const int *icPtr=_nodal_connec_index->getConstPointer();
4998   int lastVal=0;
4999   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5000     {
5001       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5002       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5003       if(!cm.isQuadratic())
5004         {
5005           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5006           types.insert(typ2); newConn->pushBackSilent(typ2);
5007           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5008           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5009             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5010           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5011           newConnI->pushBackSilent(lastVal);
5012           ret->pushBackSilent(i);
5013         }
5014       else
5015         {
5016           types.insert(typ);
5017           lastVal+=(icPtr[1]-icPtr[0]);
5018           newConnI->pushBackSilent(lastVal);
5019           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5020         }
5021     }
5022   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5023   return ret.retn();
5024 }
5025
5026 /*!
5027  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5028  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5029  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5030  */
5031 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5032 {
5033   
5034   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5035   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5036   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5037 }
5038
5039 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5040 {
5041   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5042   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5043   //
5044   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5045   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5046   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5047   //
5048   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5049   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5050   DataArrayInt *conn1D=0,*conn1DI=0;
5051   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5052   DataArrayDouble *coordsTmp=0;
5053   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5054   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5055   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5056   const int *c1DPtr=conn1D->begin();
5057   const int *c1DIPtr=conn1DI->begin();
5058   int nbOfCells=getNumberOfCells();
5059   const int *cPtr=_nodal_connec->getConstPointer();
5060   const int *icPtr=_nodal_connec_index->getConstPointer();
5061   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5062   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5063     {
5064       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5065       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5066       if(!cm.isQuadratic())
5067         {
5068           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5069           types.insert(typ2); newConn->pushBackSilent(typ2);
5070           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5071           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5072             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5073           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5074           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5075           newConnI->pushBackSilent(lastVal);
5076           ret->pushBackSilent(i);
5077         }
5078       else
5079         {
5080           types.insert(typ);
5081           lastVal+=(icPtr[1]-icPtr[0]);
5082           newConnI->pushBackSilent(lastVal);
5083           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5084         }
5085     }
5086   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5087   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5088   return ret.retn();
5089 }
5090
5091 /*!
5092  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5093  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5094  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5095  */
5096 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5097 {
5098   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5099   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5100   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5101 }
5102
5103 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5104 {
5105   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5106   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5107   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5108   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5109   //
5110   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5111   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5112   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5113   //
5114   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5115   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5116   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5117   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5118   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5119   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5120   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5121   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5122   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5123   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5124   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5125   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5126   int nbOfCells=getNumberOfCells();
5127   const int *cPtr=_nodal_connec->getConstPointer();
5128   const int *icPtr=_nodal_connec_index->getConstPointer();
5129   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5130   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5131     {
5132       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5133       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5134       if(!cm.isQuadratic())
5135         {
5136           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5137           if(typ2==INTERP_KERNEL::NORM_ERROR)
5138             {
5139               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5140               throw INTERP_KERNEL::Exception(oss.str().c_str());
5141             }
5142           types.insert(typ2); newConn->pushBackSilent(typ2);
5143           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5144           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5145             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5146           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5147             {
5148               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5149               int tmpPos=newConn->getNumberOfTuples();
5150               newConn->pushBackSilent(nodeId2);
5151               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5152             }
5153           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5154           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5155           newConnI->pushBackSilent(lastVal);
5156           ret->pushBackSilent(i);
5157         }
5158       else
5159         {
5160           types.insert(typ);
5161           lastVal+=(icPtr[1]-icPtr[0]);
5162           newConnI->pushBackSilent(lastVal);
5163           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5164         }
5165     }
5166   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5167   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5168   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5169   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5170   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5171   int *c=newConn->getPointer();
5172   const int *cI(newConnI->begin());
5173   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5174     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5175   offset=coordsTmp2Safe->getNumberOfTuples();
5176   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5177     c[cI[(*elt)+1]-1]+=offset;
5178   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5179   return ret.retn();
5180 }
5181
5182 /*!
5183  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5184  * so that the number of cells remains the same. Quadratic faces are converted to
5185  * polygons. This method works only for 2D meshes in
5186  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5187  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5188  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5189  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5190  *         a polylinized edge constituting the input polygon.
5191  *  \throw If the coordinates array is not set.
5192  *  \throw If the nodal connectivity of cells is not defined.
5193  *  \throw If \a this->getMeshDimension() != 2.
5194  *  \throw If \a this->getSpaceDimension() != 2.
5195  */
5196 void MEDCouplingUMesh::tessellate2D(double eps)
5197 {
5198   checkFullyDefined();
5199   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5200     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5201   double epsa=fabs(eps);
5202   if(epsa<std::numeric_limits<double>::min())
5203     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 !");
5204   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5205   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5206   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5207   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5208   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5209   revDesc1=0; revDescIndx1=0;
5210   mDesc->tessellate2DCurve(eps);
5211   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5212   setCoords(mDesc->getCoords());
5213 }
5214
5215 /*!
5216  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5217  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5218  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5219  *         a sub-divided edge.
5220  *  \throw If the coordinates array is not set.
5221  *  \throw If the nodal connectivity of cells is not defined.
5222  *  \throw If \a this->getMeshDimension() != 1.
5223  *  \throw If \a this->getSpaceDimension() != 2.
5224  */
5225 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5226 {
5227   checkFullyDefined();
5228   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5229     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5230   double epsa=fabs(eps);
5231   if(epsa<std::numeric_limits<double>::min())
5232     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 !");
5233   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5234   int nbCells=getNumberOfCells();
5235   int nbNodes=getNumberOfNodes();
5236   const int *conn=_nodal_connec->getConstPointer();
5237   const int *connI=_nodal_connec_index->getConstPointer();
5238   const double *coords=_coords->getConstPointer();
5239   std::vector<double> addCoo;
5240   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5241   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5242   newConnI->alloc(nbCells+1,1);
5243   int *newConnIPtr=newConnI->getPointer();
5244   *newConnIPtr=0;
5245   int tmp1[3];
5246   INTERP_KERNEL::Node *tmp2[3];
5247   std::set<INTERP_KERNEL::NormalizedCellType> types;
5248   for(int i=0;i<nbCells;i++,newConnIPtr++)
5249     {
5250       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5251       if(cm.isQuadratic())
5252         {//assert(connI[i+1]-connI[i]-1==3)
5253           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5254           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5255           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5256           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5257           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5258           if(eac)
5259             {
5260               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5261               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5262               delete eac;
5263               newConnIPtr[1]=(int)newConn.size();
5264             }
5265           else
5266             {
5267               types.insert(INTERP_KERNEL::NORM_SEG2);
5268               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5269               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5270               newConnIPtr[1]=newConnIPtr[0]+3;
5271             }
5272         }
5273       else
5274         {
5275           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5276           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5277           newConnIPtr[1]=newConnIPtr[0]+3;
5278         }
5279     }
5280   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5281     return ;
5282   _types=types;
5283   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5284   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5285   newConnArr->alloc((int)newConn.size(),1);
5286   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5287   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5288   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5289   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5290   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5291   std::copy(addCoo.begin(),addCoo.end(),work);
5292   DataArrayDouble::SetArrayIn(newCoords,_coords);
5293   updateTime();
5294 }
5295
5296 /*!
5297  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5298  * In addition, returns an array mapping new cells to old ones. <br>
5299  * This method typically increases the number of cells in \a this mesh
5300  * but the number of nodes remains \b unchanged.
5301  * That's why the 3D splitting policies
5302  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5303  *  \param [in] policy - specifies a pattern used for splitting.
5304  * The semantic of \a policy is:
5305  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5306  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5307  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5308  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5309  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5310  *          an id of old cell producing it. The caller is to delete this array using
5311  *         decrRef() as it is no more needed. 
5312  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5313  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5314  *          and \a this->getMeshDimension() != 3. 
5315  *  \throw If \a policy is not one of the four discussed above.
5316  *  \throw If the nodal connectivity of cells is not defined.
5317  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5318  */
5319 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5320 {
5321   switch(policy)
5322     {
5323     case 0:
5324       return simplexizePol0();
5325     case 1:
5326       return simplexizePol1();
5327     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5328       return simplexizePlanarFace5();
5329     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5330       return simplexizePlanarFace6();
5331     default:
5332       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)");
5333     }
5334 }
5335
5336 /*!
5337  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5338  * - 1D: INTERP_KERNEL::NORM_SEG2
5339  * - 2D: INTERP_KERNEL::NORM_TRI3
5340  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5341  *
5342  * This method is useful for users that need to use P1 field services as
5343  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5344  * All these methods need mesh support containing only simplex cells.
5345  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5346  *  \throw If the coordinates array is not set.
5347  *  \throw If the nodal connectivity of cells is not defined.
5348  *  \throw If \a this->getMeshDimension() < 1.
5349  */
5350 bool MEDCouplingUMesh::areOnlySimplexCells() const
5351 {
5352   checkFullyDefined();
5353   int mdim=getMeshDimension();
5354   if(mdim<1 || mdim>3)
5355     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5356   int nbCells=getNumberOfCells();
5357   const int *conn=_nodal_connec->getConstPointer();
5358   const int *connI=_nodal_connec_index->getConstPointer();
5359   for(int i=0;i<nbCells;i++)
5360     {
5361       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5362       if(!cm.isSimplex())
5363         return false;
5364     }
5365   return true;
5366 }
5367
5368 /*!
5369  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5370  */
5371 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5372 {
5373   checkConnectivityFullyDefined();
5374   if(getMeshDimension()!=2)
5375     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5376   int nbOfCells=getNumberOfCells();
5377   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5378   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5379   ret->alloc(nbOfCells+nbOfCutCells,1);
5380   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5381   int *retPt=ret->getPointer();
5382   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5383   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5384   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5385   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5386   int *pt=newConn->getPointer();
5387   int *ptI=newConnI->getPointer();
5388   ptI[0]=0;
5389   const int *oldc=_nodal_connec->getConstPointer();
5390   const int *ci=_nodal_connec_index->getConstPointer();
5391   for(int i=0;i<nbOfCells;i++,ci++)
5392     {
5393       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5394         {
5395           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5396                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5397           pt=std::copy(tmp,tmp+8,pt);
5398           ptI[1]=ptI[0]+4;
5399           ptI[2]=ptI[0]+8;
5400           *retPt++=i;
5401           *retPt++=i;
5402           ptI+=2;
5403         }
5404       else
5405         {
5406           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5407           ptI[1]=ptI[0]+ci[1]-ci[0];
5408           ptI++;
5409           *retPt++=i;
5410         }
5411     }
5412   _nodal_connec->decrRef();
5413   _nodal_connec=newConn.retn();
5414   _nodal_connec_index->decrRef();
5415   _nodal_connec_index=newConnI.retn();
5416   computeTypes();
5417   updateTime();
5418   return ret.retn();
5419 }
5420
5421 /*!
5422  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5423  */
5424 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5425 {
5426   checkConnectivityFullyDefined();
5427   if(getMeshDimension()!=2)
5428     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5429   int nbOfCells=getNumberOfCells();
5430   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5431   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5432   ret->alloc(nbOfCells+nbOfCutCells,1);
5433   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5434   int *retPt=ret->getPointer();
5435   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5436   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5437   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5438   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5439   int *pt=newConn->getPointer();
5440   int *ptI=newConnI->getPointer();
5441   ptI[0]=0;
5442   const int *oldc=_nodal_connec->getConstPointer();
5443   const int *ci=_nodal_connec_index->getConstPointer();
5444   for(int i=0;i<nbOfCells;i++,ci++)
5445     {
5446       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5447         {
5448           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5449                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5450           pt=std::copy(tmp,tmp+8,pt);
5451           ptI[1]=ptI[0]+4;
5452           ptI[2]=ptI[0]+8;
5453           *retPt++=i;
5454           *retPt++=i;
5455           ptI+=2;
5456         }
5457       else
5458         {
5459           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5460           ptI[1]=ptI[0]+ci[1]-ci[0];
5461           ptI++;
5462           *retPt++=i;
5463         }
5464     }
5465   _nodal_connec->decrRef();
5466   _nodal_connec=newConn.retn();
5467   _nodal_connec_index->decrRef();
5468   _nodal_connec_index=newConnI.retn();
5469   computeTypes();
5470   updateTime();
5471   return ret.retn();
5472 }
5473
5474 /*!
5475  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5476  */
5477 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5478 {
5479   checkConnectivityFullyDefined();
5480   if(getMeshDimension()!=3)
5481     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5482   int nbOfCells=getNumberOfCells();
5483   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5484   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5485   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5486   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5487   int *retPt=ret->getPointer();
5488   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5489   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5490   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5491   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5492   int *pt=newConn->getPointer();
5493   int *ptI=newConnI->getPointer();
5494   ptI[0]=0;
5495   const int *oldc=_nodal_connec->getConstPointer();
5496   const int *ci=_nodal_connec_index->getConstPointer();
5497   for(int i=0;i<nbOfCells;i++,ci++)
5498     {
5499       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5500         {
5501           for(int j=0;j<5;j++,pt+=5,ptI++)
5502             {
5503               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5504               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];
5505               *retPt++=i;
5506               ptI[1]=ptI[0]+5;
5507             }
5508         }
5509       else
5510         {
5511           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5512           ptI[1]=ptI[0]+ci[1]-ci[0];
5513           ptI++;
5514           *retPt++=i;
5515         }
5516     }
5517   _nodal_connec->decrRef();
5518   _nodal_connec=newConn.retn();
5519   _nodal_connec_index->decrRef();
5520   _nodal_connec_index=newConnI.retn();
5521   computeTypes();
5522   updateTime();
5523   return ret.retn();
5524 }
5525
5526 /*!
5527  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5528  */
5529 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5530 {
5531   checkConnectivityFullyDefined();
5532   if(getMeshDimension()!=3)
5533     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5534   int nbOfCells=getNumberOfCells();
5535   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5536   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5537   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5538   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5539   int *retPt=ret->getPointer();
5540   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5541   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5542   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5543   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5544   int *pt=newConn->getPointer();
5545   int *ptI=newConnI->getPointer();
5546   ptI[0]=0;
5547   const int *oldc=_nodal_connec->getConstPointer();
5548   const int *ci=_nodal_connec_index->getConstPointer();
5549   for(int i=0;i<nbOfCells;i++,ci++)
5550     {
5551       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5552         {
5553           for(int j=0;j<6;j++,pt+=5,ptI++)
5554             {
5555               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5556               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];
5557               *retPt++=i;
5558               ptI[1]=ptI[0]+5;
5559             }
5560         }
5561       else
5562         {
5563           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5564           ptI[1]=ptI[0]+ci[1]-ci[0];
5565           ptI++;
5566           *retPt++=i;
5567         }
5568     }
5569   _nodal_connec->decrRef();
5570   _nodal_connec=newConn.retn();
5571   _nodal_connec_index->decrRef();
5572   _nodal_connec_index=newConnI.retn();
5573   computeTypes();
5574   updateTime();
5575   return ret.retn();
5576 }
5577
5578 /*!
5579  * 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.
5580  * This method completly ignore coordinates.
5581  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5582  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5583  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5584  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5585  */
5586 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5587 {
5588   checkFullyDefined();
5589   if(getMeshDimension()!=2)
5590     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5591   int nbOfCells=getNumberOfCells();
5592   int *connI=_nodal_connec_index->getPointer();
5593   int newConnLgth=0;
5594   for(int i=0;i<nbOfCells;i++,connI++)
5595     {
5596       int offset=descIndex[i];
5597       int nbOfEdges=descIndex[i+1]-offset;
5598       //
5599       bool ddirect=desc[offset+nbOfEdges-1]>0;
5600       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5601       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5602       for(int j=0;j<nbOfEdges;j++)
5603         {
5604           bool direct=desc[offset+j]>0;
5605           int edgeId=std::abs(desc[offset+j])-1;
5606           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5607             {
5608               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5609               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5610               int ref2=direct?id1:id2;
5611               if(ref==ref2)
5612                 {
5613                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5614                   newConnLgth+=nbOfSubNodes-1;
5615                   ref=direct?id2:id1;
5616                 }
5617               else
5618                 {
5619                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5620                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5621                 }
5622             }
5623           else
5624             {
5625               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5626             }
5627         }
5628       newConnLgth++;//+1 is for cell type
5629       connI[1]=newConnLgth;
5630     }
5631   //
5632   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5633   newConn->alloc(newConnLgth,1);
5634   int *work=newConn->getPointer();
5635   for(int i=0;i<nbOfCells;i++)
5636     {
5637       *work++=INTERP_KERNEL::NORM_POLYGON;
5638       int offset=descIndex[i];
5639       int nbOfEdges=descIndex[i+1]-offset;
5640       for(int j=0;j<nbOfEdges;j++)
5641         {
5642           bool direct=desc[offset+j]>0;
5643           int edgeId=std::abs(desc[offset+j])-1;
5644           if(direct)
5645             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5646           else
5647             {
5648               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5649               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5650               work=std::copy(it,it+nbOfSubNodes-1,work);
5651             }
5652         }
5653     }
5654   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5655   _types.clear();
5656   if(nbOfCells>0)
5657     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5658 }
5659
5660 /*!
5661  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5662  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5663  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5664  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5665  * so it can be useful to call mergeNodes() before calling this method.
5666  *  \throw If \a this->getMeshDimension() <= 1.
5667  *  \throw If the coordinates array is not set.
5668  *  \throw If the nodal connectivity of cells is not defined.
5669  */
5670 void MEDCouplingUMesh::convertDegeneratedCells()
5671 {
5672   checkFullyDefined();
5673   if(getMeshDimension()<=1)
5674     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5675   int nbOfCells=getNumberOfCells();
5676   if(nbOfCells<1)
5677     return ;
5678   int initMeshLgth=getMeshLength();
5679   int *conn=_nodal_connec->getPointer();
5680   int *index=_nodal_connec_index->getPointer();
5681   int posOfCurCell=0;
5682   int newPos=0;
5683   int lgthOfCurCell;
5684   for(int i=0;i<nbOfCells;i++)
5685     {
5686       lgthOfCurCell=index[i+1]-posOfCurCell;
5687       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5688       int newLgth;
5689       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5690                                                                                                      conn+newPos+1,newLgth);
5691       conn[newPos]=newType;
5692       newPos+=newLgth+1;
5693       posOfCurCell=index[i+1];
5694       index[i+1]=newPos;
5695     }
5696   if(newPos!=initMeshLgth)
5697     _nodal_connec->reAlloc(newPos);
5698   computeTypes();
5699 }
5700
5701 /*!
5702  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5703  * A cell is considered to be oriented correctly if an angle between its
5704  * normal vector and a given vector is less than \c PI / \c 2.
5705  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5706  *         cells. 
5707  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5708  *         checked.
5709  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5710  *         is not cleared before filling in.
5711  *  \throw If \a this->getMeshDimension() != 2.
5712  *  \throw If \a this->getSpaceDimension() != 3.
5713  *
5714  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5715  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5716  */
5717 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5718 {
5719   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5720     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5721   int nbOfCells=getNumberOfCells();
5722   const int *conn=_nodal_connec->getConstPointer();
5723   const int *connI=_nodal_connec_index->getConstPointer();
5724   const double *coordsPtr=_coords->getConstPointer();
5725   for(int i=0;i<nbOfCells;i++)
5726     {
5727       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5728       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5729         {
5730           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5731           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5732             cells.push_back(i);
5733         }
5734     }
5735 }
5736
5737 /*!
5738  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5739  * considered to be oriented correctly if an angle between its normal vector and a
5740  * given vector is less than \c PI / \c 2. 
5741  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5742  *         cells. 
5743  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5744  *         checked.
5745  *  \throw If \a this->getMeshDimension() != 2.
5746  *  \throw If \a this->getSpaceDimension() != 3.
5747  *
5748  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5749  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5750  */
5751 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5752 {
5753   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5754     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5755   int nbOfCells=getNumberOfCells();
5756   int *conn=_nodal_connec->getPointer();
5757   const int *connI=_nodal_connec_index->getConstPointer();
5758   const double *coordsPtr=_coords->getConstPointer();
5759   bool isModified=false;
5760   for(int i=0;i<nbOfCells;i++)
5761     {
5762       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5763       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5764         {
5765           bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5766           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5767             {
5768               isModified=true;
5769               if(!isQuadratic)
5770                 {
5771                   std::vector<int> tmp(connI[i+1]-connI[i]-2);
5772                   std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5773                   std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5774                 }
5775               else
5776                 {
5777                   int sz(((int)(connI[i+1]-connI[i]-1))/2);
5778                   std::vector<int> tmp0(sz-1),tmp1(sz);
5779                   std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5780                   std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5781                   std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5782                   std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5783                 }
5784             }
5785         }
5786     }
5787   if(isModified)
5788     _nodal_connec->declareAsNew();
5789   updateTime();
5790 }
5791
5792 /*!
5793  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5794  * oriented facets. The normal vector of the facet should point out of the cell.
5795  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5796  *         is not cleared before filling in.
5797  *  \throw If \a this->getMeshDimension() != 3.
5798  *  \throw If \a this->getSpaceDimension() != 3.
5799  *  \throw If the coordinates array is not set.
5800  *  \throw If the nodal connectivity of cells is not defined.
5801  *
5802  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5803  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5804  */
5805 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5806 {
5807   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5808     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5809   int nbOfCells=getNumberOfCells();
5810   const int *conn=_nodal_connec->getConstPointer();
5811   const int *connI=_nodal_connec_index->getConstPointer();
5812   const double *coordsPtr=_coords->getConstPointer();
5813   for(int i=0;i<nbOfCells;i++)
5814     {
5815       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5816       if(type==INTERP_KERNEL::NORM_POLYHED)
5817         {
5818           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5819             cells.push_back(i);
5820         }
5821     }
5822 }
5823
5824 /*!
5825  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5826  * out of the cell. 
5827  *  \throw If \a this->getMeshDimension() != 3.
5828  *  \throw If \a this->getSpaceDimension() != 3.
5829  *  \throw If the coordinates array is not set.
5830  *  \throw If the nodal connectivity of cells is not defined.
5831  *  \throw If the reparation fails.
5832  *
5833  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5834  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5835  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5836  */
5837 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5838 {
5839   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5840     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5841   int nbOfCells=getNumberOfCells();
5842   int *conn=_nodal_connec->getPointer();
5843   const int *connI=_nodal_connec_index->getConstPointer();
5844   const double *coordsPtr=_coords->getConstPointer();
5845   for(int i=0;i<nbOfCells;i++)
5846     {
5847       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5848       if(type==INTERP_KERNEL::NORM_POLYHED)
5849         {
5850           try
5851             {
5852               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5853                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5854             }
5855           catch(INTERP_KERNEL::Exception& e)
5856             {
5857               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5858               throw INTERP_KERNEL::Exception(oss.str().c_str());
5859             }
5860         }
5861     }
5862   updateTime();
5863 }
5864
5865 /*!
5866  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5867  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5868  * according to which the first facet of the cell should be oriented to have the normal vector
5869  * pointing out of cell.
5870  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5871  *         cells. The caller is to delete this array using decrRef() as it is no more
5872  *         needed. 
5873  *  \throw If \a this->getMeshDimension() != 3.
5874  *  \throw If \a this->getSpaceDimension() != 3.
5875  *  \throw If the coordinates array is not set.
5876  *  \throw If the nodal connectivity of cells is not defined.
5877  *
5878  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5879  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5880  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5881  */
5882 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5883 {
5884   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5885   if(getMeshDimension()!=3)
5886     throw INTERP_KERNEL::Exception(msg);
5887   int spaceDim=getSpaceDimension();
5888   if(spaceDim!=3)
5889     throw INTERP_KERNEL::Exception(msg);
5890   //
5891   int nbOfCells=getNumberOfCells();
5892   int *conn=_nodal_connec->getPointer();
5893   const int *connI=_nodal_connec_index->getConstPointer();
5894   const double *coo=getCoords()->getConstPointer();
5895   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5896   for(int i=0;i<nbOfCells;i++)
5897     {
5898       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5899       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5900         {
5901           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5902             {
5903               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5904               cells->pushBackSilent(i);
5905             }
5906         }
5907     }
5908   return cells.retn();
5909 }
5910
5911 /*!
5912  * This method is a faster method to correct orientation of all 3D cells in \a this.
5913  * 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.
5914  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5915  * 
5916  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5917  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5918  */
5919 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
5920 {
5921   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5922     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5923   int nbOfCells=getNumberOfCells();
5924   int *conn=_nodal_connec->getPointer();
5925   const int *connI=_nodal_connec_index->getConstPointer();
5926   const double *coordsPtr=_coords->getConstPointer();
5927   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5928   for(int i=0;i<nbOfCells;i++)
5929     {
5930       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5931       switch(type)
5932         {
5933         case INTERP_KERNEL::NORM_TETRA4:
5934           {
5935             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5936               {
5937                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5938                 ret->pushBackSilent(i);
5939               }
5940             break;
5941           }
5942         case INTERP_KERNEL::NORM_PYRA5:
5943           {
5944             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5945               {
5946                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5947                 ret->pushBackSilent(i);
5948               }
5949             break;
5950           }
5951         case INTERP_KERNEL::NORM_PENTA6:
5952         case INTERP_KERNEL::NORM_HEXA8:
5953         case INTERP_KERNEL::NORM_HEXGP12:
5954           {
5955             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5956               {
5957                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5958                 ret->pushBackSilent(i);
5959               }
5960             break;
5961           }
5962         case INTERP_KERNEL::NORM_POLYHED:
5963           {
5964             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5965               {
5966                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5967                 ret->pushBackSilent(i);
5968               }
5969             break;
5970           }
5971         default:
5972           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 !");
5973         }
5974     }
5975   updateTime();
5976   return ret.retn();
5977 }
5978
5979 /*!
5980  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5981  * If it is not the case an exception will be thrown.
5982  * This method is fast because the first cell of \a this is used to compute the plane.
5983  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5984  * \param pos output of size at least 3 used to store a point owned of searched plane.
5985  */
5986 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
5987 {
5988   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5989     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5990   const int *conn=_nodal_connec->getConstPointer();
5991   const int *connI=_nodal_connec_index->getConstPointer();
5992   const double *coordsPtr=_coords->getConstPointer();
5993   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5994   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5995 }
5996
5997 /*!
5998  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5999  * cells. Currently cells of the following types are treated:
6000  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6001  * For a cell of other type an exception is thrown.
6002  * Space dimension of a 2D mesh can be either 2 or 3.
6003  * The Edge Ratio of a cell \f$t\f$ is: 
6004  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6005  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6006  *  the smallest edge lengths of \f$t\f$.
6007  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6008  *          cells and one time, lying on \a this mesh. The caller is to delete this
6009  *          field using decrRef() as it is no more needed. 
6010  *  \throw If the coordinates array is not set.
6011  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6012  *  \throw If the connectivity data array has more than one component.
6013  *  \throw If the connectivity data array has a named component.
6014  *  \throw If the connectivity index data array has more than one component.
6015  *  \throw If the connectivity index data array has a named component.
6016  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6017  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6018  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6019  */
6020 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6021 {
6022   checkCoherency();
6023   int spaceDim=getSpaceDimension();
6024   int meshDim=getMeshDimension();
6025   if(spaceDim!=2 && spaceDim!=3)
6026     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6027   if(meshDim!=2 && meshDim!=3)
6028     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6029   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6030   ret->setMesh(this);
6031   int nbOfCells=getNumberOfCells();
6032   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6033   arr->alloc(nbOfCells,1);
6034   double *pt=arr->getPointer();
6035   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6036   const int *conn=_nodal_connec->getConstPointer();
6037   const int *connI=_nodal_connec_index->getConstPointer();
6038   const double *coo=_coords->getConstPointer();
6039   double tmp[12];
6040   for(int i=0;i<nbOfCells;i++,pt++)
6041     {
6042       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6043       switch(t)
6044         {
6045           case INTERP_KERNEL::NORM_TRI3:
6046             {
6047               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6048               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6049               break;
6050             }
6051           case INTERP_KERNEL::NORM_QUAD4:
6052             {
6053               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6054               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6055               break;
6056             }
6057           case INTERP_KERNEL::NORM_TETRA4:
6058             {
6059               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6060               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6061               break;
6062             }
6063         default:
6064           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6065         }
6066       conn+=connI[i+1]-connI[i];
6067     }
6068   ret->setName("EdgeRatio");
6069   ret->synchronizeTimeWithSupport();
6070   return ret.retn();
6071 }
6072
6073 /*!
6074  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6075  * cells. Currently cells of the following types are treated:
6076  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6077  * For a cell of other type an exception is thrown.
6078  * Space dimension of a 2D mesh can be either 2 or 3.
6079  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6080  *          cells and one time, lying on \a this mesh. The caller is to delete this
6081  *          field using decrRef() as it is no more needed. 
6082  *  \throw If the coordinates array is not set.
6083  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6084  *  \throw If the connectivity data array has more than one component.
6085  *  \throw If the connectivity data array has a named component.
6086  *  \throw If the connectivity index data array has more than one component.
6087  *  \throw If the connectivity index data array has a named component.
6088  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6089  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6090  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6091  */
6092 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6093 {
6094   checkCoherency();
6095   int spaceDim=getSpaceDimension();
6096   int meshDim=getMeshDimension();
6097   if(spaceDim!=2 && spaceDim!=3)
6098     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6099   if(meshDim!=2 && meshDim!=3)
6100     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6101   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6102   ret->setMesh(this);
6103   int nbOfCells=getNumberOfCells();
6104   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6105   arr->alloc(nbOfCells,1);
6106   double *pt=arr->getPointer();
6107   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6108   const int *conn=_nodal_connec->getConstPointer();
6109   const int *connI=_nodal_connec_index->getConstPointer();
6110   const double *coo=_coords->getConstPointer();
6111   double tmp[12];
6112   for(int i=0;i<nbOfCells;i++,pt++)
6113     {
6114       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6115       switch(t)
6116         {
6117           case INTERP_KERNEL::NORM_TRI3:
6118             {
6119               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6120               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6121               break;
6122             }
6123           case INTERP_KERNEL::NORM_QUAD4:
6124             {
6125               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6126               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6127               break;
6128             }
6129           case INTERP_KERNEL::NORM_TETRA4:
6130             {
6131               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6132               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6133               break;
6134             }
6135         default:
6136           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6137         }
6138       conn+=connI[i+1]-connI[i];
6139     }
6140   ret->setName("AspectRatio");
6141   ret->synchronizeTimeWithSupport();
6142   return ret.retn();
6143 }
6144
6145 /*!
6146  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6147  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6148  * treated: INTERP_KERNEL::NORM_QUAD4.
6149  * For a cell of other type an exception is thrown.
6150  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6151  *          cells and one time, lying on \a this mesh. The caller is to delete this
6152  *          field using decrRef() as it is no more needed. 
6153  *  \throw If the coordinates array is not set.
6154  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6155  *  \throw If the connectivity data array has more than one component.
6156  *  \throw If the connectivity data array has a named component.
6157  *  \throw If the connectivity index data array has more than one component.
6158  *  \throw If the connectivity index data array has a named component.
6159  *  \throw If \a this->getMeshDimension() != 2.
6160  *  \throw If \a this->getSpaceDimension() != 3.
6161  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6162  */
6163 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6164 {
6165   checkCoherency();
6166   int spaceDim=getSpaceDimension();
6167   int meshDim=getMeshDimension();
6168   if(spaceDim!=3)
6169     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6170   if(meshDim!=2)
6171     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6172   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6173   ret->setMesh(this);
6174   int nbOfCells=getNumberOfCells();
6175   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6176   arr->alloc(nbOfCells,1);
6177   double *pt=arr->getPointer();
6178   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6179   const int *conn=_nodal_connec->getConstPointer();
6180   const int *connI=_nodal_connec_index->getConstPointer();
6181   const double *coo=_coords->getConstPointer();
6182   double tmp[12];
6183   for(int i=0;i<nbOfCells;i++,pt++)
6184     {
6185       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6186       switch(t)
6187         {
6188           case INTERP_KERNEL::NORM_QUAD4:
6189             {
6190               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6191               *pt=INTERP_KERNEL::quadWarp(tmp);
6192               break;
6193             }
6194         default:
6195           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6196         }
6197       conn+=connI[i+1]-connI[i];
6198     }
6199   ret->setName("Warp");
6200   ret->synchronizeTimeWithSupport();
6201   return ret.retn();
6202 }
6203
6204
6205 /*!
6206  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6207  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6208  * treated: INTERP_KERNEL::NORM_QUAD4.
6209  * For a cell of other type an exception is thrown.
6210  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6211  *          cells and one time, lying on \a this mesh. The caller is to delete this
6212  *          field using decrRef() as it is no more needed. 
6213  *  \throw If the coordinates array is not set.
6214  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6215  *  \throw If the connectivity data array has more than one component.
6216  *  \throw If the connectivity data array has a named component.
6217  *  \throw If the connectivity index data array has more than one component.
6218  *  \throw If the connectivity index data array has a named component.
6219  *  \throw If \a this->getMeshDimension() != 2.
6220  *  \throw If \a this->getSpaceDimension() != 3.
6221  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6222  */
6223 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6224 {
6225   checkCoherency();
6226   int spaceDim=getSpaceDimension();
6227   int meshDim=getMeshDimension();
6228   if(spaceDim!=3)
6229     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6230   if(meshDim!=2)
6231     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6232   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6233   ret->setMesh(this);
6234   int nbOfCells=getNumberOfCells();
6235   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6236   arr->alloc(nbOfCells,1);
6237   double *pt=arr->getPointer();
6238   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6239   const int *conn=_nodal_connec->getConstPointer();
6240   const int *connI=_nodal_connec_index->getConstPointer();
6241   const double *coo=_coords->getConstPointer();
6242   double tmp[12];
6243   for(int i=0;i<nbOfCells;i++,pt++)
6244     {
6245       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6246       switch(t)
6247         {
6248           case INTERP_KERNEL::NORM_QUAD4:
6249             {
6250               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6251               *pt=INTERP_KERNEL::quadSkew(tmp);
6252               break;
6253             }
6254         default:
6255           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6256         }
6257       conn+=connI[i+1]-connI[i];
6258     }
6259   ret->setName("Skew");
6260   ret->synchronizeTimeWithSupport();
6261   return ret.retn();
6262 }
6263
6264 /*!
6265  * This method aggregate the bbox of each cell and put it into bbox parameter.
6266  * 
6267  * \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)
6268  *                         For all other cases this input parameter is ignored.
6269  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6270  * 
6271  * \throw If \a this is not fully set (coordinates and connectivity).
6272  * \throw If a cell in \a this has no valid nodeId.
6273  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6274  */
6275 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6276 {
6277   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6278   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.
6279     return getBoundingBoxForBBTreeFast();
6280   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6281     {
6282       bool presenceOfQuadratic(false);
6283       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6284         {
6285           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6286           if(cm.isQuadratic())
6287             presenceOfQuadratic=true;
6288         }
6289       if(!presenceOfQuadratic)
6290         return getBoundingBoxForBBTreeFast();
6291       if(mDim==2 && sDim==2)
6292         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6293       else
6294         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6295     }
6296   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) !");
6297 }
6298
6299 /*!
6300  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6301  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6302  * 
6303  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6304  * 
6305  * \throw If \a this is not fully set (coordinates and connectivity).
6306  * \throw If a cell in \a this has no valid nodeId.
6307  */
6308 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6309 {
6310   checkFullyDefined();
6311   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6312   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6313   double *bbox(ret->getPointer());
6314   for(int i=0;i<nbOfCells*spaceDim;i++)
6315     {
6316       bbox[2*i]=std::numeric_limits<double>::max();
6317       bbox[2*i+1]=-std::numeric_limits<double>::max();
6318     }
6319   const double *coordsPtr(_coords->getConstPointer());
6320   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6321   for(int i=0;i<nbOfCells;i++)
6322     {
6323       int offset=connI[i]+1;
6324       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6325       for(int j=0;j<nbOfNodesForCell;j++)
6326         {
6327           int nodeId=conn[offset+j];
6328           if(nodeId>=0 && nodeId<nbOfNodes)
6329             {
6330               for(int k=0;k<spaceDim;k++)
6331                 {
6332                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6333                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6334                 }
6335               kk++;
6336             }
6337         }
6338       if(kk==0)
6339         {
6340           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6341           throw INTERP_KERNEL::Exception(oss.str().c_str());
6342         }
6343     }
6344   return ret.retn();
6345 }
6346
6347 /*!
6348  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6349  * useful for 2D meshes having quadratic cells
6350  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6351  * the two extremities of the arc of circle).
6352  * 
6353  * \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)
6354  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6355  * \throw If \a this is not fully defined.
6356  * \throw If \a this is not a mesh with meshDimension equal to 2.
6357  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6358  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6359  */
6360 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6361 {
6362   checkFullyDefined();
6363   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6364   if(spaceDim!=2 || mDim!=2)
6365     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!");
6366   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6367   double *bbox(ret->getPointer());
6368   const double *coords(_coords->getConstPointer());
6369   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6370   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6371     {
6372       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6373       int sz(connI[1]-connI[0]-1);
6374       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6375       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6376       INTERP_KERNEL::QuadraticPolygon *pol(0);
6377       for(int j=0;j<sz;j++)
6378         {
6379           int nodeId(conn[*connI+1+j]);
6380           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6381         }
6382       if(!cm.isQuadratic())
6383         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6384       else
6385         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6386       INTERP_KERNEL::Bounds b; pol->fillBounds(b); delete pol;
6387       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6388     }
6389   return ret.retn();
6390 }
6391
6392 /*!
6393  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6394  * useful for 2D meshes having quadratic cells
6395  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6396  * the two extremities of the arc of circle).
6397  * 
6398  * \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)
6399  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6400  * \throw If \a this is not fully defined.
6401  * \throw If \a this is not a mesh with meshDimension equal to 1.
6402  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6403  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6404  */
6405 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6406 {
6407   checkFullyDefined();
6408   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6409   if(spaceDim!=2 || mDim!=1)
6410     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!");
6411   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6412   double *bbox(ret->getPointer());
6413   const double *coords(_coords->getConstPointer());
6414   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6415   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6416     {
6417       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6418       int sz(connI[1]-connI[0]-1);
6419       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6420       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6421       INTERP_KERNEL::Edge *edge(0);
6422       for(int j=0;j<sz;j++)
6423         {
6424           int nodeId(conn[*connI+1+j]);
6425           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6426         }
6427       if(!cm.isQuadratic())
6428         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6429       else
6430         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6431       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6432       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6433     }
6434   return ret.retn();
6435 }
6436
6437 /// @cond INTERNAL
6438
6439 namespace ParaMEDMEMImpl
6440 {
6441   class ConnReader
6442   {
6443   public:
6444     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6445     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6446   private:
6447     const int *_conn;
6448     int _val;
6449   };
6450
6451   class ConnReader2
6452   {
6453   public:
6454     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6455     bool operator() (const int& pos) { return _conn[pos]==_val; }
6456   private:
6457     const int *_conn;
6458     int _val;
6459   };
6460 }
6461
6462 /// @endcond
6463
6464 /*!
6465  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6466  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6467  * \a this is composed in cell types.
6468  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6469  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6470  * This parameter is kept only for compatibility with other methode listed above.
6471  */
6472 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6473 {
6474   checkConnectivityFullyDefined();
6475   const int *conn=_nodal_connec->getConstPointer();
6476   const int *connI=_nodal_connec_index->getConstPointer();
6477   const int *work=connI;
6478   int nbOfCells=getNumberOfCells();
6479   std::size_t n=getAllGeoTypes().size();
6480   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6481   std::set<INTERP_KERNEL::NormalizedCellType> types;
6482   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6483     {
6484       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6485       if(types.find(typ)!=types.end())
6486         {
6487           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6488           oss << " is not contiguous !";
6489           throw INTERP_KERNEL::Exception(oss.str().c_str());
6490         }
6491       types.insert(typ);
6492       ret[3*i]=typ;
6493       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6494       ret[3*i+1]=(int)std::distance(work,work2);
6495       work=work2;
6496     }
6497   return ret;
6498 }
6499
6500 /*!
6501  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6502  * only for types cell, type node is not managed.
6503  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6504  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6505  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6506  * If 2 or more same geometric type is in \a code and exception is thrown too.
6507  *
6508  * This method firstly checks
6509  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6510  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6511  * an exception is thrown too.
6512  * 
6513  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6514  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6515  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6516  */
6517 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6518 {
6519   if(code.empty())
6520     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6521   std::size_t sz=code.size();
6522   std::size_t n=sz/3;
6523   if(sz%3!=0)
6524     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6525   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6526   int nb=0;
6527   bool isNoPflUsed=true;
6528   for(std::size_t i=0;i<n;i++)
6529     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6530       {
6531         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6532         nb+=code[3*i+1];
6533         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6534           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6535         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6536       }
6537   if(types.size()!=n)
6538     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6539   if(isNoPflUsed)
6540     {
6541       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6542         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6543       if(types.size()==_types.size())
6544         return 0;
6545     }
6546   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6547   ret->alloc(nb,1);
6548   int *retPtr=ret->getPointer();
6549   const int *connI=_nodal_connec_index->getConstPointer();
6550   const int *conn=_nodal_connec->getConstPointer();
6551   int nbOfCells=getNumberOfCells();
6552   const int *i=connI;
6553   int kk=0;
6554   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6555     {
6556       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6557       int offset=(int)std::distance(connI,i);
6558       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6559       int nbOfCellsOfCurType=(int)std::distance(i,j);
6560       if(code[3*kk+2]==-1)
6561         for(int k=0;k<nbOfCellsOfCurType;k++)
6562           *retPtr++=k+offset;
6563       else
6564         {
6565           int idInIdsPerType=code[3*kk+2];
6566           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6567             {
6568               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6569               if(zePfl)
6570                 {
6571                   zePfl->checkAllocated();
6572                   if(zePfl->getNumberOfComponents()==1)
6573                     {
6574                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6575                         {
6576                           if(*k>=0 && *k<nbOfCellsOfCurType)
6577                             *retPtr=(*k)+offset;
6578                           else
6579                             {
6580                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6581                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6582                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6583                             }
6584                         }
6585                     }
6586                   else
6587                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6588                 }
6589               else
6590                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6591             }
6592           else
6593             {
6594               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6595               oss << " should be in [0," << idsPerType.size() << ") !";
6596               throw INTERP_KERNEL::Exception(oss.str().c_str());
6597             }
6598         }
6599       i=j;
6600     }
6601   return ret.retn();
6602 }
6603
6604 /*!
6605  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6606  * 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.
6607  * 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.
6608  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6609  * 
6610  * \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.
6611  * \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,
6612  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6613  * \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.
6614  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6615  * \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
6616  */
6617 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6618 {
6619   if(!profile)
6620     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6621   if(profile->getNumberOfComponents()!=1)
6622     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6623   checkConnectivityFullyDefined();
6624   const int *conn=_nodal_connec->getConstPointer();
6625   const int *connI=_nodal_connec_index->getConstPointer();
6626   int nbOfCells=getNumberOfCells();
6627   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6628   std::vector<int> typeRangeVals(1);
6629   for(const int *i=connI;i!=connI+nbOfCells;)
6630     {
6631       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6632       if(std::find(types.begin(),types.end(),curType)!=types.end())
6633         {
6634           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6635         }
6636       types.push_back(curType);
6637       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6638       typeRangeVals.push_back((int)std::distance(connI,i));
6639     }
6640   //
6641   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6642   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6643   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6644   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6645   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6646   //
6647   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6648   code.resize(3*nbOfCastsFinal);
6649   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6650   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6651   for(int i=0;i<nbOfCastsFinal;i++)
6652     {
6653       int castId=castsPresent->getIJ(i,0);
6654       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6655       idsInPflPerType2.push_back(tmp3);
6656       code[3*i]=(int)types[castId];
6657       code[3*i+1]=tmp3->getNumberOfTuples();
6658       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6659       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6660         {
6661           tmp4->copyStringInfoFrom(*profile);
6662           idsPerType2.push_back(tmp4);
6663           code[3*i+2]=(int)idsPerType2.size()-1;
6664         }
6665       else
6666         {
6667           code[3*i+2]=-1;
6668         }
6669     }
6670   std::size_t sz2=idsInPflPerType2.size();
6671   idsInPflPerType.resize(sz2);
6672   for(std::size_t i=0;i<sz2;i++)
6673     {
6674       DataArrayInt *locDa=idsInPflPerType2[i];
6675       locDa->incrRef();
6676       idsInPflPerType[i]=locDa;
6677     }
6678   std::size_t sz=idsPerType2.size();
6679   idsPerType.resize(sz);
6680   for(std::size_t i=0;i<sz;i++)
6681     {
6682       DataArrayInt *locDa=idsPerType2[i];
6683       locDa->incrRef();
6684       idsPerType[i]=locDa;
6685     }
6686 }
6687
6688 /*!
6689  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6690  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6691  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6692  * 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.
6693  */
6694 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6695 {
6696   checkFullyDefined();
6697   nM1LevMesh->checkFullyDefined();
6698   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6699     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6700   if(_coords!=nM1LevMesh->getCoords())
6701     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6702   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6703   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6704   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6705   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6706   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6707   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6708   tmp->setConnectivity(tmp0,tmp1);
6709   tmp->renumberCells(ret0->getConstPointer(),false);
6710   revDesc=tmp->getNodalConnectivity();
6711   revDescIndx=tmp->getNodalConnectivityIndex();
6712   DataArrayInt *ret=0;
6713   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6714     {
6715       int tmp2;
6716       ret->getMaxValue(tmp2);
6717       ret->decrRef();
6718       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6719       throw INTERP_KERNEL::Exception(oss.str().c_str());
6720     }
6721   nM1LevMeshIds=ret;
6722   //
6723   revDesc->incrRef();
6724   revDescIndx->incrRef();
6725   ret1->incrRef();
6726   ret0->incrRef();
6727   meshnM1Old2New=ret0;
6728   return ret1;
6729 }
6730
6731 /*!
6732  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6733  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6734  * in "Old to New" mode.
6735  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6736  *          this array using decrRef() as it is no more needed.
6737  *  \throw If the nodal connectivity of cells is not defined.
6738  */
6739 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6740 {
6741   checkConnectivityFullyDefined();
6742   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6743   renumberCells(ret->getConstPointer(),false);
6744   return ret.retn();
6745 }
6746
6747 /*!
6748  * This methods checks that cells are sorted by their types.
6749  * This method makes asumption (no check) that connectivity is correctly set before calling.
6750  */
6751 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6752 {
6753   checkFullyDefined();
6754   const int *conn=_nodal_connec->getConstPointer();
6755   const int *connI=_nodal_connec_index->getConstPointer();
6756   int nbOfCells=getNumberOfCells();
6757   std::set<INTERP_KERNEL::NormalizedCellType> types;
6758   for(const int *i=connI;i!=connI+nbOfCells;)
6759     {
6760       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6761       if(types.find(curType)!=types.end())
6762         return false;
6763       types.insert(curType);
6764       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6765     }
6766   return true;
6767 }
6768
6769 /*!
6770  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6771  * The geometric type order is specified by MED file.
6772  * 
6773  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6774  */
6775 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6776 {
6777   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6778 }
6779
6780 /*!
6781  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6782  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6783  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6784  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6785  */
6786 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6787 {
6788   checkFullyDefined();
6789   const int *conn=_nodal_connec->getConstPointer();
6790   const int *connI=_nodal_connec_index->getConstPointer();
6791   int nbOfCells=getNumberOfCells();
6792   if(nbOfCells==0)
6793     return true;
6794   int lastPos=-1;
6795   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6796   for(const int *i=connI;i!=connI+nbOfCells;)
6797     {
6798       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6799       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6800       if(isTypeExists!=orderEnd)
6801         {
6802           int pos=(int)std::distance(orderBg,isTypeExists);
6803           if(pos<=lastPos)
6804             return false;
6805           lastPos=pos;
6806           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6807         }
6808       else
6809         {
6810           if(sg.find(curType)==sg.end())
6811             {
6812               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6813               sg.insert(curType);
6814             }
6815           else
6816             return false;
6817         }
6818     }
6819   return true;
6820 }
6821
6822 /*!
6823  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6824  * 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
6825  * 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'.
6826  */
6827 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6828 {
6829   checkConnectivityFullyDefined();
6830   int nbOfCells=getNumberOfCells();
6831   const int *conn=_nodal_connec->getConstPointer();
6832   const int *connI=_nodal_connec_index->getConstPointer();
6833   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6834   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6835   tmpa->alloc(nbOfCells,1);
6836   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6837   tmpb->fillWithZero();
6838   int *tmp=tmpa->getPointer();
6839   int *tmp2=tmpb->getPointer();
6840   for(const int *i=connI;i!=connI+nbOfCells;i++)
6841     {
6842       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6843       if(where!=orderEnd)
6844         {
6845           int pos=(int)std::distance(orderBg,where);
6846           tmp2[pos]++;
6847           tmp[std::distance(connI,i)]=pos;
6848         }
6849       else
6850         {
6851           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6852           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6853           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6854           throw INTERP_KERNEL::Exception(oss.str().c_str());
6855         }
6856     }
6857   nbPerType=tmpb.retn();
6858   return tmpa.retn();
6859 }
6860
6861 /*!
6862  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6863  *
6864  * \return a new object containing the old to new correspondance.
6865  *
6866  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6867  */
6868 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6869 {
6870   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6871 }
6872
6873 /*!
6874  * 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.
6875  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6876  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6877  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6878  */
6879 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6880 {
6881   DataArrayInt *nbPerType=0;
6882   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6883   nbPerType->decrRef();
6884   return tmpa->buildPermArrPerLevel();
6885 }
6886
6887 /*!
6888  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6889  * The number of cells remains unchanged after the call of this method.
6890  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6891  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6892  *
6893  * \return the array giving the correspondance old to new.
6894  */
6895 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6896 {
6897   checkFullyDefined();
6898   computeTypes();
6899   const int *conn=_nodal_connec->getConstPointer();
6900   const int *connI=_nodal_connec_index->getConstPointer();
6901   int nbOfCells=getNumberOfCells();
6902   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6903   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6904     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6905       {
6906         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6907         types.push_back(curType);
6908         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6909       }
6910   DataArrayInt *ret=DataArrayInt::New();
6911   ret->alloc(nbOfCells,1);
6912   int *retPtr=ret->getPointer();
6913   std::fill(retPtr,retPtr+nbOfCells,-1);
6914   int newCellId=0;
6915   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6916     {
6917       for(const int *i=connI;i!=connI+nbOfCells;i++)
6918         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6919           retPtr[std::distance(connI,i)]=newCellId++;
6920     }
6921   renumberCells(retPtr,false);
6922   return ret;
6923 }
6924
6925 /*!
6926  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6927  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6928  * This method makes asumption that connectivity is correctly set before calling.
6929  */
6930 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6931 {
6932   checkConnectivityFullyDefined();
6933   const int *conn=_nodal_connec->getConstPointer();
6934   const int *connI=_nodal_connec_index->getConstPointer();
6935   int nbOfCells=getNumberOfCells();
6936   std::vector<MEDCouplingUMesh *> ret;
6937   for(const int *i=connI;i!=connI+nbOfCells;)
6938     {
6939       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6940       int beginCellId=(int)std::distance(connI,i);
6941       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6942       int endCellId=(int)std::distance(connI,i);
6943       int sz=endCellId-beginCellId;
6944       int *cells=new int[sz];
6945       for(int j=0;j<sz;j++)
6946         cells[j]=beginCellId+j;
6947       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6948       delete [] cells;
6949       ret.push_back(m);
6950     }
6951   return ret;
6952 }
6953
6954 /*!
6955  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6956  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6957  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6958  *
6959  * \return a newly allocated instance, that the caller must manage.
6960  * \throw If \a this contains more than one geometric type.
6961  * \throw If the nodal connectivity of \a this is not fully defined.
6962  * \throw If the internal data is not coherent.
6963  */
6964 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
6965 {
6966   checkConnectivityFullyDefined();
6967     if(_types.size()!=1)
6968     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6969   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6970   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6971   ret->setCoords(getCoords());
6972   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6973   if(retC)
6974     {
6975       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6976       retC->setNodalConnectivity(c);
6977     }
6978   else
6979     {
6980       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6981       if(!retD)
6982         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6983       DataArrayInt *c=0,*ci=0;
6984       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6985       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6986       retD->setNodalConnectivity(cs,cis);
6987     }
6988   return ret.retn();
6989 }
6990
6991 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
6992 {
6993   checkConnectivityFullyDefined();
6994     if(_types.size()!=1)
6995     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6996   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6997   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6998   if(cm.isDynamic())
6999     {
7000       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7001       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7002       throw INTERP_KERNEL::Exception(oss.str().c_str());
7003     }
7004   int nbCells=getNumberOfCells();
7005   int typi=(int)typ;
7006   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7007   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7008   int *outPtr=connOut->getPointer();
7009   const int *conn=_nodal_connec->begin();
7010   const int *connI=_nodal_connec_index->begin();
7011   nbNodesPerCell++;
7012   for(int i=0;i<nbCells;i++,connI++)
7013     {
7014       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7015         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7016       else
7017         {
7018           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 << ") !";
7019           throw INTERP_KERNEL::Exception(oss.str().c_str());
7020         }
7021     }
7022   return connOut.retn();
7023 }
7024
7025 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7026 {
7027   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7028   checkConnectivityFullyDefined();
7029   if(_types.size()!=1)
7030     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7031   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7032   if(lgth<nbCells)
7033     throw INTERP_KERNEL::Exception(msg0);
7034   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7035   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7036   int *cp(c->getPointer()),*cip(ci->getPointer());
7037   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7038   cip[0]=0;
7039   for(int i=0;i<nbCells;i++,cip++,incip++)
7040     {
7041       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7042       int delta(stop-strt);
7043       if(delta>=1)
7044         {
7045           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7046             cp=std::copy(incp+strt,incp+stop,cp);
7047           else
7048             throw INTERP_KERNEL::Exception(msg0);
7049         }
7050       else
7051         throw INTERP_KERNEL::Exception(msg0);
7052       cip[1]=cip[0]+delta;
7053     }
7054   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7055 }
7056
7057 /*!
7058  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7059  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7060  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7061  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7062  * are not used here to avoid the build of big permutation array.
7063  *
7064  * \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
7065  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7066  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7067  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7068  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7069  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7070  * \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
7071  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7072  */
7073 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7074                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7075                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
7076 {
7077   std::vector<const MEDCouplingUMesh *> ms2;
7078   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7079     if(*it)
7080       {
7081         (*it)->checkConnectivityFullyDefined();
7082         ms2.push_back(*it);
7083       }
7084   if(ms2.empty())
7085     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7086   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7087   int meshDim=ms2[0]->getMeshDimension();
7088   std::vector<const MEDCouplingUMesh *> m1ssm;
7089   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7090   //
7091   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7092   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7093   int fake=0,rk=0;
7094   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7095   ret1->alloc(0,1); ret2->alloc(0,1);
7096   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7097     {
7098       if(meshDim!=(*it)->getMeshDimension())
7099         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7100       if(refCoo!=(*it)->getCoords())
7101         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7102       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7103       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7104       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7105       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7106         {
7107           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7108           m1ssmSingleAuto.push_back(singleCell);
7109           m1ssmSingle.push_back(singleCell);
7110           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7111         }
7112     }
7113   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7114   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7115   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7116   for(std::size_t i=0;i<m1ssm.size();i++)
7117     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7118   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7119   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7120   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7121   return ret0.retn();
7122 }
7123
7124 /*!
7125  * This method returns a newly created DataArrayInt instance.
7126  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7127  */
7128 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7129 {
7130   checkFullyDefined();
7131   const int *conn=_nodal_connec->getConstPointer();
7132   const int *connIndex=_nodal_connec_index->getConstPointer();
7133   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7134   for(const int *w=begin;w!=end;w++)
7135     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7136       ret->pushBackSilent(*w);
7137   return ret.retn();
7138 }
7139
7140 /*!
7141  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7142  * are in [0:getNumberOfCells())
7143  */
7144 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7145 {
7146   checkFullyDefined();
7147   const int *conn=_nodal_connec->getConstPointer();
7148   const int *connI=_nodal_connec_index->getConstPointer();
7149   int nbOfCells=getNumberOfCells();
7150   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7151   int *tmp=new int[nbOfCells];
7152   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7153     {
7154       int j=0;
7155       for(const int *i=connI;i!=connI+nbOfCells;i++)
7156         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7157           tmp[std::distance(connI,i)]=j++;
7158     }
7159   DataArrayInt *ret=DataArrayInt::New();
7160   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7161   ret->copyStringInfoFrom(*da);
7162   int *retPtr=ret->getPointer();
7163   const int *daPtr=da->getConstPointer();
7164   int nbOfElems=da->getNbOfElems();
7165   for(int k=0;k<nbOfElems;k++)
7166     retPtr[k]=tmp[daPtr[k]];
7167   delete [] tmp;
7168   return ret;
7169 }
7170
7171 /*!
7172  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7173  * This method \b works \b for mesh sorted by type.
7174  * cells whose ids is in 'idsPerGeoType' array.
7175  * This method conserves coords and name of mesh.
7176  */
7177 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7178 {
7179   std::vector<int> code=getDistributionOfTypes();
7180   std::size_t nOfTypesInThis=code.size()/3;
7181   int sz=0,szOfType=0;
7182   for(std::size_t i=0;i<nOfTypesInThis;i++)
7183     {
7184       if(code[3*i]!=type)
7185         sz+=code[3*i+1];
7186       else
7187         szOfType=code[3*i+1];
7188     }
7189   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7190     if(*work<0 || *work>=szOfType)
7191       {
7192         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7193         oss << ". It should be in [0," << szOfType << ") !";
7194         throw INTERP_KERNEL::Exception(oss.str().c_str());
7195       }
7196   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7197   int *idsPtr=idsTokeep->getPointer();
7198   int offset=0;
7199   for(std::size_t i=0;i<nOfTypesInThis;i++)
7200     {
7201       if(code[3*i]!=type)
7202         for(int j=0;j<code[3*i+1];j++)
7203           *idsPtr++=offset+j;
7204       else
7205         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7206       offset+=code[3*i+1];
7207     }
7208   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7209   ret->copyTinyInfoFrom(this);
7210   return ret.retn();
7211 }
7212
7213 /*!
7214  * This method returns a vector of size 'this->getNumberOfCells()'.
7215  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7216  */
7217 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7218 {
7219   int ncell=getNumberOfCells();
7220   std::vector<bool> ret(ncell);
7221   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7222   const int *c=getNodalConnectivity()->getConstPointer();
7223   for(int i=0;i<ncell;i++)
7224     {
7225       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7226       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7227       ret[i]=cm.isQuadratic();
7228     }
7229   return ret;
7230 }
7231
7232 /*!
7233  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7234  */
7235 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7236 {
7237   if(other->getType()!=UNSTRUCTURED)
7238     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7239   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7240   return MergeUMeshes(this,otherC);
7241 }
7242
7243 /*!
7244  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7245  * computed by averaging coordinates of cell nodes, so this method is not a right
7246  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7247  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7248  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7249  *          components. The caller is to delete this array using decrRef() as it is
7250  *          no more needed.
7251  *  \throw If the coordinates array is not set.
7252  *  \throw If the nodal connectivity of cells is not defined.
7253  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7254  */
7255 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7256 {
7257   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7258   int spaceDim=getSpaceDimension();
7259   int nbOfCells=getNumberOfCells();
7260   ret->alloc(nbOfCells,spaceDim);
7261   ret->copyStringInfoFrom(*getCoords());
7262   double *ptToFill=ret->getPointer();
7263   const int *nodal=_nodal_connec->getConstPointer();
7264   const int *nodalI=_nodal_connec_index->getConstPointer();
7265   const double *coor=_coords->getConstPointer();
7266   for(int i=0;i<nbOfCells;i++)
7267     {
7268       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7269       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7270       ptToFill+=spaceDim;
7271     }
7272   return ret.retn();
7273 }
7274
7275 /*!
7276  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7277  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7278  * 
7279  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7280  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7281  * 
7282  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7283  * \throw If \a this is not fully defined (coordinates and connectivity)
7284  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7285  */
7286 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7287 {
7288   checkFullyDefined();
7289   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7290   int spaceDim=getSpaceDimension();
7291   int nbOfCells=getNumberOfCells();
7292   int nbOfNodes=getNumberOfNodes();
7293   ret->alloc(nbOfCells,spaceDim);
7294   double *ptToFill=ret->getPointer();
7295   const int *nodal=_nodal_connec->getConstPointer();
7296   const int *nodalI=_nodal_connec_index->getConstPointer();
7297   const double *coor=_coords->getConstPointer();
7298   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7299     {
7300       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7301       std::fill(ptToFill,ptToFill+spaceDim,0.);
7302       if(type!=INTERP_KERNEL::NORM_POLYHED)
7303         {
7304           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7305             {
7306               if(*conn>=0 && *conn<nbOfNodes)
7307                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7308               else
7309                 {
7310                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7311                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7312                 }
7313             }
7314           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7315           if(nbOfNodesInCell>0)
7316             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7317           else
7318             {
7319               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7320               throw INTERP_KERNEL::Exception(oss.str().c_str());
7321             }
7322         }
7323       else
7324         {
7325           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7326           s.erase(-1);
7327           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7328             {
7329               if(*it>=0 && *it<nbOfNodes)
7330                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7331               else
7332                 {
7333                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7334                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7335                 }
7336             }
7337           if(!s.empty())
7338             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7339           else
7340             {
7341               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7342               throw INTERP_KERNEL::Exception(oss.str().c_str());
7343             }
7344         }
7345     }
7346   return ret.retn();
7347 }
7348
7349 /*!
7350  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7351  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7352  * are specified via an array of cell ids. 
7353  *  \warning Validity of the specified cell ids is not checked! 
7354  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7355  *  \param [in] begin - an array of cell ids of interest.
7356  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7357  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7358  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7359  *          caller is to delete this array using decrRef() as it is no more needed. 
7360  *  \throw If the coordinates array is not set.
7361  *  \throw If the nodal connectivity of cells is not defined.
7362  *
7363  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7364  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7365  */
7366 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7367 {
7368   DataArrayDouble *ret=DataArrayDouble::New();
7369   int spaceDim=getSpaceDimension();
7370   int nbOfTuple=(int)std::distance(begin,end);
7371   ret->alloc(nbOfTuple,spaceDim);
7372   double *ptToFill=ret->getPointer();
7373   double *tmp=new double[spaceDim];
7374   const int *nodal=_nodal_connec->getConstPointer();
7375   const int *nodalI=_nodal_connec_index->getConstPointer();
7376   const double *coor=_coords->getConstPointer();
7377   for(const int *w=begin;w!=end;w++)
7378     {
7379       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7380       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7381       ptToFill+=spaceDim;
7382     }
7383   delete [] tmp;
7384   return ret;
7385 }
7386
7387 /*!
7388  * 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".
7389  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7390  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7391  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7392  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7393  * 
7394  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7395  * \throw If spaceDim!=3 or meshDim!=2.
7396  * \throw If connectivity of \a this is invalid.
7397  * \throw If connectivity of a cell in \a this points to an invalid node.
7398  */
7399 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7400 {
7401   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7402   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7403   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7404     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7405   ret->alloc(nbOfCells,4);
7406   double *retPtr(ret->getPointer());
7407   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7408   const double *coor(_coords->begin());
7409   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7410     {
7411       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7412       if(nodalI[1]-nodalI[0]>=3)
7413         {
7414           for(int j=0;j<3;j++)
7415             {
7416               int nodeId(nodal[nodalI[0]+1+j]);
7417               if(nodeId>=0 && nodeId<nbOfNodes)
7418                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7419               else
7420                 {
7421                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7422                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7423                 }
7424             }
7425         }
7426       else
7427         {
7428           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7429           throw INTERP_KERNEL::Exception(oss.str().c_str());
7430         }
7431       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7432       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7433     }
7434   return ret.retn();
7435 }
7436
7437 /*!
7438  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7439  * 
7440  */
7441 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7442 {
7443   if(!da)
7444     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7445   da->checkAllocated();
7446   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7447   ret->setCoords(da);
7448   int nbOfTuples=da->getNumberOfTuples();
7449   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7450   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7451   c->alloc(2*nbOfTuples,1);
7452   cI->alloc(nbOfTuples+1,1);
7453   int *cp=c->getPointer();
7454   int *cip=cI->getPointer();
7455   *cip++=0;
7456   for(int i=0;i<nbOfTuples;i++)
7457     {
7458       *cp++=INTERP_KERNEL::NORM_POINT1;
7459       *cp++=i;
7460       *cip++=2*(i+1);
7461     }
7462   ret->setConnectivity(c,cI,true);
7463   return ret.retn();
7464 }
7465 /*!
7466  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7467  * Cells and nodes of
7468  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7469  *  \param [in] mesh1 - the first mesh.
7470  *  \param [in] mesh2 - the second mesh.
7471  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7472  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7473  *          is no more needed.
7474  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7475  *  \throw If the coordinates array is not set in none of the meshes.
7476  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7477  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7478  */
7479 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7480 {
7481   std::vector<const MEDCouplingUMesh *> tmp(2);
7482   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7483   return MergeUMeshes(tmp);
7484 }
7485
7486 /*!
7487  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7488  * Cells and nodes of
7489  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7490  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7491  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7492  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7493  *          is no more needed.
7494  *  \throw If \a a.size() == 0.
7495  *  \throw If \a a[ *i* ] == NULL.
7496  *  \throw If the coordinates array is not set in none of the meshes.
7497  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7498  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7499 */
7500 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7501 {
7502   std::size_t sz=a.size();
7503   if(sz==0)
7504     return MergeUMeshesLL(a);
7505   for(std::size_t ii=0;ii<sz;ii++)
7506     if(!a[ii])
7507       {
7508         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7509         throw INTERP_KERNEL::Exception(oss.str().c_str());
7510       }
7511   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7512   std::vector< const MEDCouplingUMesh * > aa(sz);
7513   int spaceDim=-3;
7514   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7515     {
7516       const MEDCouplingUMesh *cur=a[i];
7517       const DataArrayDouble *coo=cur->getCoords();
7518       if(coo)
7519         spaceDim=coo->getNumberOfComponents();
7520     }
7521   if(spaceDim==-3)
7522     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7523   for(std::size_t i=0;i<sz;i++)
7524     {
7525       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7526       aa[i]=bb[i];
7527     }
7528   return MergeUMeshesLL(aa);
7529 }
7530
7531 /// @cond INTERNAL
7532
7533 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7534 {
7535   if(a.empty())
7536     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7537   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7538   int meshDim=(*it)->getMeshDimension();
7539   int nbOfCells=(*it)->getNumberOfCells();
7540   int meshLgth=(*it++)->getMeshLength();
7541   for(;it!=a.end();it++)
7542     {
7543       if(meshDim!=(*it)->getMeshDimension())
7544         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7545       nbOfCells+=(*it)->getNumberOfCells();
7546       meshLgth+=(*it)->getMeshLength();
7547     }
7548   std::vector<const MEDCouplingPointSet *> aps(a.size());
7549   std::copy(a.begin(),a.end(),aps.begin());
7550   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7551   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7552   ret->setCoords(pts);
7553   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7554   c->alloc(meshLgth,1);
7555   int *cPtr=c->getPointer();
7556   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7557   cI->alloc(nbOfCells+1,1);
7558   int *cIPtr=cI->getPointer();
7559   *cIPtr++=0;
7560   int offset=0;
7561   int offset2=0;
7562   for(it=a.begin();it!=a.end();it++)
7563     {
7564       int curNbOfCell=(*it)->getNumberOfCells();
7565       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7566       const int *curC=(*it)->_nodal_connec->getConstPointer();
7567       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7568       for(int j=0;j<curNbOfCell;j++)
7569         {
7570           const int *src=curC+curCI[j];
7571           *cPtr++=*src++;
7572           for(;src!=curC+curCI[j+1];src++,cPtr++)
7573             {
7574               if(*src!=-1)
7575                 *cPtr=*src+offset2;
7576               else
7577                 *cPtr=-1;
7578             }
7579         }
7580       offset+=curCI[curNbOfCell];
7581       offset2+=(*it)->getNumberOfNodes();
7582     }
7583   //
7584   ret->setConnectivity(c,cI,true);
7585   return ret.retn();
7586 }
7587
7588 /// @endcond
7589
7590 /*!
7591  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7592  * dimension and sharing the node coordinates array.
7593  * All cells of the first mesh precede all cells of the second mesh
7594  * within the result mesh. 
7595  *  \param [in] mesh1 - the first mesh.
7596  *  \param [in] mesh2 - the second mesh.
7597  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7598  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7599  *          is no more needed.
7600  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7601  *  \throw If the meshes do not share the node coordinates array.
7602  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7603  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7604  */
7605 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7606 {
7607   std::vector<const MEDCouplingUMesh *> tmp(2);
7608   tmp[0]=mesh1; tmp[1]=mesh2;
7609   return MergeUMeshesOnSameCoords(tmp);
7610 }
7611
7612 /*!
7613  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7614  * dimension and sharing the node coordinates array.
7615  * All cells of the *i*-th mesh precede all cells of the
7616  * (*i*+1)-th mesh within the result mesh.
7617  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7618  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7619  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7620  *          is no more needed.
7621  *  \throw If \a a.size() == 0.
7622  *  \throw If \a a[ *i* ] == NULL.
7623  *  \throw If the meshes do not share the node coordinates array.
7624  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7625  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7626  */
7627 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7628 {
7629   if(meshes.empty())
7630     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7631   for(std::size_t ii=0;ii<meshes.size();ii++)
7632     if(!meshes[ii])
7633       {
7634         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7635         throw INTERP_KERNEL::Exception(oss.str().c_str());
7636       }
7637   const DataArrayDouble *coords=meshes.front()->getCoords();
7638   int meshDim=meshes.front()->getMeshDimension();
7639   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7640   int meshLgth=0;
7641   int meshIndexLgth=0;
7642   for(;iter!=meshes.end();iter++)
7643     {
7644       if(coords!=(*iter)->getCoords())
7645         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7646       if(meshDim!=(*iter)->getMeshDimension())
7647         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7648       meshLgth+=(*iter)->getMeshLength();
7649       meshIndexLgth+=(*iter)->getNumberOfCells();
7650     }
7651   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7652   nodal->alloc(meshLgth,1);
7653   int *nodalPtr=nodal->getPointer();
7654   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7655   nodalIndex->alloc(meshIndexLgth+1,1);
7656   int *nodalIndexPtr=nodalIndex->getPointer();
7657   int offset=0;
7658   for(iter=meshes.begin();iter!=meshes.end();iter++)
7659     {
7660       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7661       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7662       int nbOfCells=(*iter)->getNumberOfCells();
7663       int meshLgth2=(*iter)->getMeshLength();
7664       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7665       if(iter!=meshes.begin())
7666         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7667       else
7668         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7669       offset+=meshLgth2;
7670     }
7671   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7672   ret->setName("merge");
7673   ret->setMeshDimension(meshDim);
7674   ret->setConnectivity(nodal,nodalIndex,true);
7675   ret->setCoords(coords);
7676   return ret;
7677 }
7678
7679 /*!
7680  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7681  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7682  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7683  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7684  * New" mode are returned for each input mesh.
7685  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7686  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7687  *          valid values [0,1,2], see zipConnectivityTraducer().
7688  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7689  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7690  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7691  *          no more needed.
7692  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7693  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7694  *          is no more needed.
7695  *  \throw If \a meshes.size() == 0.
7696  *  \throw If \a meshes[ *i* ] == NULL.
7697  *  \throw If the meshes do not share the node coordinates array.
7698  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7699  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7700  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7701  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7702  */
7703 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7704 {
7705   //All checks are delegated to MergeUMeshesOnSameCoords
7706   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7707   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7708   corr.resize(meshes.size());
7709   std::size_t nbOfMeshes=meshes.size();
7710   int offset=0;
7711   const int *o2nPtr=o2n->getConstPointer();
7712   for(std::size_t i=0;i<nbOfMeshes;i++)
7713     {
7714       DataArrayInt *tmp=DataArrayInt::New();
7715       int curNbOfCells=meshes[i]->getNumberOfCells();
7716       tmp->alloc(curNbOfCells,1);
7717       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7718       offset+=curNbOfCells;
7719       tmp->setName(meshes[i]->getName());
7720       corr[i]=tmp;
7721     }
7722   return ret.retn();
7723 }
7724
7725 /*!
7726  * Makes all given meshes share the nodal connectivity array. The common connectivity
7727  * array is created by concatenating the connectivity arrays of all given meshes. All
7728  * the given meshes must be of the same space dimension but dimension of cells **can
7729  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7730  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7731  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7732  *  \param [in,out] meshes - a vector of meshes to update.
7733  *  \throw If any of \a meshes is NULL.
7734  *  \throw If the coordinates array is not set in any of \a meshes.
7735  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7736  *  \throw If \a meshes are of different space dimension.
7737  */
7738 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7739 {
7740   std::size_t sz=meshes.size();
7741   if(sz==0 || sz==1)
7742     return;
7743   std::vector< const DataArrayDouble * > coords(meshes.size());
7744   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7745   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7746     {
7747       if((*it))
7748         {
7749           (*it)->checkConnectivityFullyDefined();
7750           const DataArrayDouble *coo=(*it)->getCoords();
7751           if(coo)
7752             *it2=coo;
7753           else
7754             {
7755               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7756               oss << " has no coordinate array defined !";
7757               throw INTERP_KERNEL::Exception(oss.str().c_str());
7758             }
7759         }
7760       else
7761         {
7762           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7763           oss << " is null !";
7764           throw INTERP_KERNEL::Exception(oss.str().c_str());
7765         }
7766     }
7767   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7768   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7769   int offset=(*it)->getNumberOfNodes();
7770   (*it++)->setCoords(res);
7771   for(;it!=meshes.end();it++)
7772     {
7773       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7774       (*it)->setCoords(res);
7775       (*it)->shiftNodeNumbersInConn(offset);
7776       offset+=oldNumberOfNodes;
7777     }
7778 }
7779
7780 /*!
7781  * Merges nodes coincident with a given precision within all given meshes that share
7782  * the nodal connectivity array. The given meshes **can be of different** mesh
7783  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7784  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7785  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7786  *  \param [in,out] meshes - a vector of meshes to update.
7787  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7788  *  \throw If any of \a meshes is NULL.
7789  *  \throw If the \a meshes do not share the same node coordinates array.
7790  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7791  */
7792 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7793 {
7794   if(meshes.empty())
7795     return ;
7796   std::set<const DataArrayDouble *> s;
7797   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7798     {
7799       if(*it)
7800         s.insert((*it)->getCoords());
7801       else
7802         {
7803           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 !";
7804           throw INTERP_KERNEL::Exception(oss.str().c_str());
7805         }
7806     }
7807   if(s.size()!=1)
7808     {
7809       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 !";
7810       throw INTERP_KERNEL::Exception(oss.str().c_str());
7811     }
7812   const DataArrayDouble *coo=*(s.begin());
7813   if(!coo)
7814     return;
7815   //
7816   DataArrayInt *comm,*commI;
7817   coo->findCommonTuples(eps,-1,comm,commI);
7818   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7819   int oldNbOfNodes=coo->getNumberOfTuples();
7820   int newNbOfNodes;
7821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7822   if(oldNbOfNodes==newNbOfNodes)
7823     return ;
7824   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7825   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7826     {
7827       (*it)->renumberNodesInConn(o2n->getConstPointer());
7828       (*it)->setCoords(newCoords);
7829     } 
7830 }
7831
7832 /*!
7833  * 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.
7834  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7835  * \param isQuad specifies the policy of connectivity.
7836  * @ret in/out parameter in which the result will be append
7837  */
7838 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7839 {
7840   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7841   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7842   ret.push_back(cm.getExtrudedType());
7843   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7844   switch(flatType)
7845     {
7846     case INTERP_KERNEL::NORM_POINT1:
7847       {
7848         ret.push_back(connBg[1]);
7849         ret.push_back(connBg[1]+nbOfNodesPerLev);
7850         break;
7851       }
7852     case INTERP_KERNEL::NORM_SEG2:
7853       {
7854         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7855         ret.insert(ret.end(),conn,conn+4);
7856         break;
7857       }
7858     case INTERP_KERNEL::NORM_SEG3:
7859       {
7860         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7861         ret.insert(ret.end(),conn,conn+8);
7862         break;
7863       }
7864     case INTERP_KERNEL::NORM_QUAD4:
7865       {
7866         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7867         ret.insert(ret.end(),conn,conn+8);
7868         break;
7869       }
7870     case INTERP_KERNEL::NORM_TRI3:
7871       {
7872         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7873         ret.insert(ret.end(),conn,conn+6);
7874         break;
7875       }
7876     case INTERP_KERNEL::NORM_TRI6:
7877       {
7878         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,
7879                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7880         ret.insert(ret.end(),conn,conn+15);
7881         break;
7882       }
7883     case INTERP_KERNEL::NORM_QUAD8:
7884       {
7885         int conn[20]={
7886           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7887           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7888           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7889         };
7890         ret.insert(ret.end(),conn,conn+20);
7891         break;
7892       }
7893     case INTERP_KERNEL::NORM_POLYGON:
7894       {
7895         std::back_insert_iterator< std::vector<int> > ii(ret);
7896         std::copy(connBg+1,connEnd,ii);
7897         *ii++=-1;
7898         std::reverse_iterator<const int *> rConnBg(connEnd);
7899         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7900         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7901         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7902         for(std::size_t i=0;i<nbOfRadFaces;i++)
7903           {
7904             *ii++=-1;
7905             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7906             std::copy(conn,conn+4,ii);
7907           }
7908         break;
7909       }
7910     default:
7911       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7912     }
7913 }
7914
7915 /*!
7916  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7917  */
7918 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7919 {
7920   std::size_t i, ip1;
7921   double v[3]={0.,0.,0.};
7922   std::size_t sz=std::distance(begin,end);
7923   if(isQuadratic)
7924     sz/=2;
7925   for(i=0;i<sz;i++)
7926     {
7927       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];
7928       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7929       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7930     }
7931   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
7932
7933   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
7934   // SEG3 forming a circle):
7935   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
7936     {
7937       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
7938       for(std::size_t j=0;j<sz;j++)
7939         {
7940           if (j%2)  // current point i is quadratic, next point i+1 is standard
7941             {
7942               i = sz+j;
7943               ip1 = (j+1)%sz; // ip1 = "i+1"
7944             }
7945           else      // current point i is standard, next point i+1 is quadratic
7946             {
7947               i = j;
7948               ip1 = j+sz;
7949             }
7950           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
7951           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
7952           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
7953         }
7954       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
7955     }
7956   return (ret>0.);
7957 }
7958
7959 /*!
7960  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7961  */
7962 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7963 {
7964   std::vector<std::pair<int,int> > edges;
7965   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7966   const int *bgFace=begin;
7967   for(std::size_t i=0;i<nbOfFaces;i++)
7968     {
7969       const int *endFace=std::find(bgFace+1,end,-1);
7970       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7971       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7972         {
7973           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7974           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7975             return false;
7976           edges.push_back(p1);
7977         }
7978       bgFace=endFace+1;
7979     }
7980   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7981 }
7982
7983 /*!
7984  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7985  */
7986 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7987 {
7988   double vec0[3],vec1[3];
7989   std::size_t sz=std::distance(begin,end);
7990   if(sz%2!=0)
7991     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7992   int nbOfNodes=(int)sz/2;
7993   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7994   const double *pt0=coords+3*begin[0];
7995   const double *pt1=coords+3*begin[nbOfNodes];
7996   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7997   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7998 }
7999
8000 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8001 {
8002   std::size_t sz=std::distance(begin,end);
8003   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8004   std::size_t nbOfNodes(sz/2);
8005   std::copy(begin,end,(int *)tmp);
8006   for(std::size_t j=1;j<nbOfNodes;j++)
8007     {
8008       begin[j]=tmp[nbOfNodes-j];
8009       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8010     }
8011 }
8012
8013 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8014 {
8015   std::size_t sz=std::distance(begin,end);
8016   if(sz!=4)
8017     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8018   double vec0[3],vec1[3];
8019   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8020   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]; 
8021   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;
8022 }
8023
8024 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8025 {
8026   std::size_t sz=std::distance(begin,end);
8027   if(sz!=5)
8028     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8029   double vec0[3];
8030   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8031   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8032   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8033 }
8034
8035 /*!
8036  * 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 ) 
8037  * 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
8038  * a 2D space.
8039  *
8040  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8041  * \param [in] coords the coordinates with nb of components exactly equal to 3
8042  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8043  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8044  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8045  */
8046 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8047 {
8048   int nbFaces=std::count(begin+1,end,-1)+1;
8049   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8050   double *vPtr=v->getPointer();
8051   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8052   double *pPtr=p->getPointer();
8053   const int *stFaceConn=begin+1;
8054   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8055     {
8056       const int *endFaceConn=std::find(stFaceConn,end,-1);
8057       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8058       stFaceConn=endFaceConn+1;
8059     }
8060   pPtr=p->getPointer(); vPtr=v->getPointer();
8061   DataArrayInt *comm1=0,*commI1=0;
8062   v->findCommonTuples(eps,-1,comm1,commI1);
8063   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8064   const int *comm1Ptr=comm1->getConstPointer();
8065   const int *commI1Ptr=commI1->getConstPointer();
8066   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8067   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8068   //
8069   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8070   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8071   mm->finishInsertingCells();
8072   //
8073   for(int i=0;i<nbOfGrps1;i++)
8074     {
8075       int vecId=comm1Ptr[commI1Ptr[i]];
8076       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8077       DataArrayInt *comm2=0,*commI2=0;
8078       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8079       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8080       const int *comm2Ptr=comm2->getConstPointer();
8081       const int *commI2Ptr=commI2->getConstPointer();
8082       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8083       for(int j=0;j<nbOfGrps2;j++)
8084         {
8085           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8086             {
8087               res->insertAtTheEnd(begin,end);
8088               res->pushBackSilent(-1);
8089             }
8090           else
8091             {
8092               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8093               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8094               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8095               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8096               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8097               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8098               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8099               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8100               const int *idsNodePtr=idsNode->getConstPointer();
8101               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];
8102               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8103               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8104               if(std::abs(norm)>eps)
8105                 {
8106                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8107                   mm3->rotate(center,vec,angle);
8108                 }
8109               mm3->changeSpaceDimension(2);
8110               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8111               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8112               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8113               int nbOfCells=mm4->getNumberOfCells();
8114               for(int k=0;k<nbOfCells;k++)
8115                 {
8116                   int l=0;
8117                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8118                     res->pushBackSilent(idsNodePtr[*work]);
8119                   res->pushBackSilent(-1);
8120                 }
8121             }
8122         }
8123     }
8124   res->popBackSilent();
8125 }
8126
8127 /*!
8128  * 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
8129  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8130  * 
8131  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8132  * \param [in] coords coordinates expected to have 3 components.
8133  * \param [in] begin start of the nodal connectivity of the face.
8134  * \param [in] end end of the nodal connectivity (excluded) of the face.
8135  * \param [out] v the normalized vector of size 3
8136  * \param [out] p the pos of plane
8137  */
8138 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8139 {
8140   std::size_t nbPoints=std::distance(begin,end);
8141   if(nbPoints<3)
8142     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8143   double vec[3]={0.,0.,0.};
8144   std::size_t j=0;
8145   bool refFound=false;
8146   for(;j<nbPoints-1 && !refFound;j++)
8147     {
8148       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8149       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8150       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8151       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8152       if(norm>eps)
8153         {
8154           refFound=true;
8155           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8156         }
8157     }
8158   for(std::size_t i=j;i<nbPoints-1;i++)
8159     {
8160       double curVec[3];
8161       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8162       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8163       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8164       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8165       if(norm<eps)
8166         continue;
8167       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8168       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];
8169       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8170       if(norm>eps)
8171         {
8172           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8173           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8174           return ;
8175         }
8176     }
8177   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8178 }
8179
8180 /*!
8181  * This method tries to obtain a well oriented polyhedron.
8182  * If the algorithm fails, an exception will be thrown.
8183  */
8184 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8185 {
8186   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8187   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8188   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8189   isPerm[0]=true;
8190   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8191   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8192   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8193   //
8194   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8195     {
8196       bgFace=begin;
8197       std::size_t smthChanged=0;
8198       for(std::size_t i=0;i<nbOfFaces;i++)
8199         {
8200           endFace=std::find(bgFace+1,end,-1);
8201           nbOfEdgesInFace=std::distance(bgFace,endFace);
8202           if(!isPerm[i])
8203             {
8204               bool b;
8205               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8206                 {
8207                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8208                   std::pair<int,int> p2(p1.second,p1.first);
8209                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8210                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8211                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8212                 }
8213               if(isPerm[i])
8214                 { 
8215                   if(!b)
8216                     std::reverse(bgFace+1,endFace);
8217                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8218                     {
8219                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8220                       std::pair<int,int> p2(p1.second,p1.first);
8221                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8222                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8223                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8224                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8225                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8226                       if(it!=edgesOK.end())
8227                         {
8228                           edgesOK.erase(it);
8229                           edgesFinished.push_back(p1);
8230                         }
8231                       else
8232                         edgesOK.push_back(p1);
8233                     }
8234                 }
8235             }
8236           bgFace=endFace+1;
8237         }
8238       if(smthChanged==0)
8239         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8240     }
8241   if(!edgesOK.empty())
8242     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8243   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8244     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8245       bgFace=begin;
8246       for(std::size_t i=0;i<nbOfFaces;i++)
8247         {
8248           endFace=std::find(bgFace+1,end,-1);
8249           std::reverse(bgFace+1,endFace);
8250           bgFace=endFace+1;
8251         }
8252     }
8253 }
8254
8255 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8256 {
8257   int nbOfNodesExpected(skin->getNumberOfNodes());
8258   const int *n2oPtr(n2o->getConstPointer());
8259   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8260   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8261   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8262   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8263   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8264   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8265   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8266   if(nbOfNodesExpected<1)
8267     return ret.retn();
8268   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8269   *work++=n2oPtr[prevNode];
8270   for(int i=1;i<nbOfNodesExpected;i++)
8271     {
8272       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8273         {
8274           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8275           conn.erase(prevNode);
8276           if(conn.size()==1)
8277             {
8278               int curNode(*(conn.begin()));
8279               *work++=n2oPtr[curNode];
8280               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8281               shar.erase(prevCell);
8282               if(shar.size()==1)
8283                 {
8284                   prevCell=*(shar.begin());
8285                   prevNode=curNode;
8286                 }
8287               else
8288                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8289             }
8290           else
8291             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8292         }
8293       else
8294         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8295     }
8296   return ret.retn();
8297 }
8298
8299 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8300 {
8301   int nbOfNodesExpected(skin->getNumberOfNodes());
8302   int nbOfTurn(nbOfNodesExpected/2);
8303   const int *n2oPtr(n2o->getConstPointer());
8304   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8305   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8306   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8307   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8308   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8309   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8310   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8311   if(nbOfNodesExpected<1)
8312     return ret.retn();
8313   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8314   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8315   for(int i=1;i<nbOfTurn;i++)
8316     {
8317       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8318         {
8319           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8320           conn.erase(prevNode);
8321           if(conn.size()==1)
8322             {
8323               int curNode(*(conn.begin()));
8324               *work=n2oPtr[curNode];
8325               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8326               shar.erase(prevCell);
8327               if(shar.size()==1)
8328                 {
8329                   int curCell(*(shar.begin()));
8330                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8331                   prevCell=curCell;
8332                   prevNode=curNode;
8333                   work++;
8334                 }
8335               else
8336                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8337             }
8338           else
8339             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8340         }
8341       else
8342         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8343     }
8344   return ret.retn();
8345 }
8346
8347 /*!
8348  * This method makes the assumption spacedimension == meshdimension == 2.
8349  * This method works only for linear cells.
8350  * 
8351  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8352  */
8353 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8354 {
8355   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8356     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8357   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8358   int oldNbOfNodes(skin->getNumberOfNodes());
8359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8360   int nbOfNodesExpected(skin->getNumberOfNodes());
8361   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8362   int nbCells(skin->getNumberOfCells());
8363   if(nbCells==nbOfNodesExpected)
8364     return buildUnionOf2DMeshLinear(skin,n2o);
8365   else if(2*nbCells==nbOfNodesExpected)
8366     return buildUnionOf2DMeshQuadratic(skin,n2o);
8367   else
8368     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8369 }
8370
8371 /*!
8372  * This method makes the assumption spacedimension == meshdimension == 3.
8373  * This method works only for linear cells.
8374  * 
8375  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8376  */
8377 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8378 {
8379   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8380     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8381   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8382   const int *conn=m->getNodalConnectivity()->getConstPointer();
8383   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8384   int nbOfCells=m->getNumberOfCells();
8385   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8386   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8387   if(nbOfCells<1)
8388     return ret.retn();
8389   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8390   for(int i=1;i<nbOfCells;i++)
8391     {
8392       *work++=-1;
8393       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8394     }
8395   return ret.retn();
8396 }
8397
8398 /*!
8399  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8400  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8401  */
8402 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8403 {
8404   double *w=zipFrmt;
8405   if(spaceDim==3)
8406     for(int i=0;i<nbOfNodesInCell;i++)
8407       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8408   else if(spaceDim==2)
8409     {
8410       for(int i=0;i<nbOfNodesInCell;i++)
8411         {
8412           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8413           *w++=0.;
8414         }
8415     }
8416   else
8417     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8418 }
8419
8420 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8421 {
8422   int nbOfCells=getNumberOfCells();
8423   if(nbOfCells<=0)
8424     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8425   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};
8426   ofs << "  <" << getVTKDataSetType() << ">\n";
8427   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8428   ofs << "      <PointData>\n" << pointData << std::endl;
8429   ofs << "      </PointData>\n";
8430   ofs << "      <CellData>\n" << cellData << std::endl;
8431   ofs << "      </CellData>\n";
8432   ofs << "      <Points>\n";
8433   if(getSpaceDimension()==3)
8434     _coords->writeVTK(ofs,8,"Points",byteData);
8435   else
8436     {
8437       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8438       coo->writeVTK(ofs,8,"Points",byteData);
8439     }
8440   ofs << "      </Points>\n";
8441   ofs << "      <Cells>\n";
8442   const int *cPtr=_nodal_connec->getConstPointer();
8443   const int *cIPtr=_nodal_connec_index->getConstPointer();
8444   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8445   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8446   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8447   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8448   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8449   int szFaceOffsets=0,szConn=0;
8450   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8451     {
8452       *w2=cPtr[cIPtr[i]];
8453       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8454         {
8455           *w1=-1;
8456           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8457           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8458         }
8459       else
8460         {
8461           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8462           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8463           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8464           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8465           w4=std::copy(c.begin(),c.end(),w4);
8466         }
8467     }
8468   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8469   types->writeVTK(ofs,8,"UInt8","types",byteData);
8470   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8471   if(szFaceOffsets!=0)
8472     {//presence of Polyhedra
8473       connectivity->reAlloc(szConn);
8474       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8475       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8476       w1=faces->getPointer();
8477       for(int i=0;i<nbOfCells;i++)
8478         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8479           {
8480             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8481             *w1++=nbFaces;
8482             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8483             for(int j=0;j<nbFaces;j++)
8484               {
8485                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8486                 *w1++=(int)std::distance(w6,w5);
8487                 w1=std::copy(w6,w5,w1);
8488                 w6=w5+1;
8489               }
8490           }
8491       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8492     }
8493   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8494   ofs << "      </Cells>\n";
8495   ofs << "    </Piece>\n";
8496   ofs << "  </" << getVTKDataSetType() << ">\n";
8497 }
8498
8499 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8500 {
8501   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8502   if(_mesh_dim==-2)
8503     { stream << " Not set !"; return ; }
8504   stream << " Mesh dimension : " << _mesh_dim << ".";
8505   if(_mesh_dim==-1)
8506     return ;
8507   if(!_coords)
8508     { stream << " No coordinates set !"; return ; }
8509   if(!_coords->isAllocated())
8510     { stream << " Coordinates set but not allocated !"; return ; }
8511   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8512   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8513   if(!_nodal_connec_index)
8514     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8515   if(!_nodal_connec_index->isAllocated())
8516     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8517   int lgth=_nodal_connec_index->getNumberOfTuples();
8518   int cpt=_nodal_connec_index->getNumberOfComponents();
8519   if(cpt!=1 || lgth<1)
8520     return ;
8521   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8522 }
8523
8524 std::string MEDCouplingUMesh::getVTKDataSetType() const
8525 {
8526   return std::string("UnstructuredGrid");
8527 }
8528
8529 /*!
8530  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8531  * returns a result mesh constituted by polygons.
8532  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8533  * all nodes from m2.
8534  * The meshes should be in 2D space. In
8535  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8536  * meshes.
8537  *  \param [in] m1 - the first input mesh which is a partitioned object.
8538  *  \param [in] m2 - the second input mesh which is a partition tool.
8539  *  \param [in] eps - precision used to detect coincident mesh entities.
8540  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8541  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8542  *         this array using decrRef() as it is no more needed.
8543  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8544  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8545  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8546  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8547  *         it is no more needed.  
8548  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8549  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8550  *         is no more needed.  
8551  *  \throw If the coordinates array is not set in any of the meshes.
8552  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8553  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8554  */
8555 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8556                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8557 {
8558   m1->checkFullyDefined();
8559   m2->checkFullyDefined();
8560   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8561     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8562
8563   // Step 1: compute all edge intersections (new nodes)
8564   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8565   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8566   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8567   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8568   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8569   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8570   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8571                                       m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8572                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8573   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8574   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8575   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8576
8577   // Step 2: re-order newly created nodes according to the ordering found in m2
8578   std::vector< std::vector<int> > intersectEdge2;
8579   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8580   subDiv2.clear(); dd5=0; dd6=0;
8581
8582   // Step 3:
8583   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8584   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8585   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8586                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8587
8588   // Step 4: Prepare final result:
8589   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8590   addCooDa->alloc((int)(addCoo.size())/2,2);
8591   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8592   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8593   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8594   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8595   std::vector<const DataArrayDouble *> coordss(4);
8596   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8597   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8598   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8599   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8600   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8601   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8602   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8603   ret->setConnectivity(conn,connI,true);
8604   ret->setCoords(coo);
8605   cellNb1=c1.retn(); cellNb2=c2.retn();
8606   return ret.retn();
8607 }
8608
8609
8610 /**
8611  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
8612  * (newly created) nodes corresponding to the edge intersections.
8613  * Output params:
8614  * @param[out] cr, crI connectivity of the resulting mesh
8615  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
8616  * TODO: describe input parameters
8617  */
8618 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8619                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8620                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8621                                                          const std::vector<double>& addCoords,
8622                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8623 {
8624   static const int SPACEDIM=2;
8625   const double *coo1=m1->getCoords()->getConstPointer();
8626   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8627   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8628   int offset1=m1->getNumberOfNodes();
8629   const double *coo2=m2->getCoords()->getConstPointer();
8630   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8631   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8632   int offset2=offset1+m2->getNumberOfNodes();
8633   int offset3=offset2+((int)addCoords.size())/2;
8634   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8635   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8636   // Here a BBTree on 2D-cells, not on segments:
8637   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8638   int ncell1=m1->getNumberOfCells();
8639   crI.push_back(0);
8640   for(int i=0;i<ncell1;i++)
8641     {
8642       std::vector<int> candidates2;
8643       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8644       std::map<INTERP_KERNEL::Node *,int> mapp;
8645       std::map<int,INTERP_KERNEL::Node *> mappRev;
8646       INTERP_KERNEL::QuadraticPolygon pol1;
8647       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8648       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8649       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
8650       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8651       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
8652       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8653                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8654       //
8655       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
8656       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8657       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8658       for(it1.first();!it1.finished();it1.next())
8659         edges1.insert(it1.current()->getPtr());
8660       //
8661       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
8662       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8663       int ii=0;
8664       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8665         {
8666           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8667           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8668           // Complete mapping with elements coming from the current cell it2 in mesh2:
8669           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8670           // pol2 is the new QP in the final merged result.
8671           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8672                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
8673         }
8674       ii=0;
8675       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8676         {
8677           pol1.initLocationsWithOther(pol2s[ii]);
8678           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8679           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8680           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8681         }
8682       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
8683       // by m2 but that we still want to keep in the final result.
8684       if(!edges1.empty())
8685         {
8686           try
8687             {
8688               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8689             }
8690           catch(INTERP_KERNEL::Exception& e)
8691             {
8692               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();
8693               throw INTERP_KERNEL::Exception(oss.str().c_str());
8694             }
8695         }
8696       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8697         (*it).second->decrRef();
8698     }
8699 }
8700
8701 /*!
8702  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8703  * It builds the descending connectivity of the two meshes, and then using a binary tree
8704  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
8705  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
8706  */
8707 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8708                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8709                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8710                                                    std::vector<double>& addCoo,
8711                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
8712                                                    throw(INTERP_KERNEL::Exception)
8713 {
8714   static const int SPACEDIM=2;
8715   // Build desc connectivity
8716   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8717   desc2=DataArrayInt::New();
8718   descIndx2=DataArrayInt::New();
8719   revDesc2=DataArrayInt::New();
8720   revDescIndx2=DataArrayInt::New();
8721   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8722   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8723   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8724   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8725   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8726   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8727   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8728
8729   // Build BB tree of all edges in the tool mesh (second mesh)
8730   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
8731   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8732   int nDescCell1=m1Desc->getNumberOfCells();
8733   int nDescCell2=m2Desc->getNumberOfCells();
8734   intersectEdge1.resize(nDescCell1);
8735   colinear2.resize(nDescCell2);
8736   subDiv2.resize(nDescCell2);
8737   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
8738
8739   std::vector<int> candidates1(1);
8740   int offset1=m1->getNumberOfNodes();
8741   int offset2=offset1+m2->getNumberOfNodes();
8742   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
8743     {
8744       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
8745       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8746       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
8747         {
8748           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8749           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
8750           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8751           candidates1[0]=i;
8752           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8753           // 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
8754           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
8755           std::set<INTERP_KERNEL::Node *> nodes;
8756           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
8757           std::size_t szz(nodes.size());
8758           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
8759           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
8760           for(std::size_t iii=0;iii<szz;iii++,itt++)
8761             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
8762           // end of protection
8763           // Performs egde cutting:
8764           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8765           delete pol2;
8766           delete pol1;
8767         }
8768       else
8769         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8770     }
8771   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8772   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8773 }
8774
8775 /*!
8776  * This method performs the 2nd step of Partition of 2D mesh.
8777  * This method has 4 inputs :
8778  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8779  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8780  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
8781  * 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'
8782  * Nodes end up lying consecutively on a cutted edge.
8783  * \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.
8784  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
8785  * \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.
8786  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
8787  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
8788  */
8789 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8790       const std::vector<double>& addCoo,
8791       const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
8792 {
8793   int offset1=m1->getNumberOfNodes();
8794   int ncell=m2->getNumberOfCells();
8795   const int *c=m2->getNodalConnectivity()->getConstPointer();
8796   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8797   const double *coo=m2->getCoords()->getConstPointer();
8798   const double *cooBis=m1->getCoords()->getConstPointer();
8799   int offset2=offset1+m2->getNumberOfNodes();
8800   intersectEdge.resize(ncell);
8801   for(int i=0;i<ncell;i++,cI++)
8802     {
8803       const std::vector<int>& divs=subDiv[i];
8804       int nnode=cI[1]-cI[0]-1;
8805       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8806       std::map<INTERP_KERNEL::Node *, int> mapp22;
8807       for(int j=0;j<nnode;j++)
8808         {
8809           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8810           int nnid=c[(*cI)+j+1];
8811           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8812           mapp22[nn]=nnid+offset1;
8813         }
8814       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8815       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8816         ((*it).second.first)->decrRef();
8817       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8818       std::map<INTERP_KERNEL::Node *,int> mapp3;
8819       for(std::size_t j=0;j<divs.size();j++)
8820         {
8821           int id=divs[j];
8822           INTERP_KERNEL::Node *tmp=0;
8823           if(id<offset1)
8824             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8825           else if(id<offset2)
8826             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8827           else
8828             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8829           addNodes[j]=tmp;
8830           mapp3[tmp]=id;
8831         }
8832       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8833       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8834         (*it)->decrRef();
8835       e->decrRef();
8836     }
8837 }
8838
8839 /*!
8840  * 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).
8841  * 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
8842  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8843  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8844  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8845  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8846  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8847  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8848  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8849  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8850  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8851  * \param [out] cut3DSuf input/output param.
8852  */
8853 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8854                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8855                                                    const int *desc, const int *descIndx, 
8856                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8857 {
8858   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8859   int nbOf3DSurfCell=(int)cut3DSurf.size();
8860   for(int i=0;i<nbOf3DSurfCell;i++)
8861     {
8862       std::vector<int> res;
8863       int offset=descIndx[i];
8864       int nbOfSeg=descIndx[i+1]-offset;
8865       for(int j=0;j<nbOfSeg;j++)
8866         {
8867           int edgeId=desc[offset+j];
8868           int status=cut3DCurve[edgeId];
8869           if(status!=-2)
8870             {
8871               if(status>-1)
8872                 res.push_back(status);
8873               else
8874                 {
8875                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8876                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8877                 }
8878             }
8879         }
8880       switch(res.size())
8881         {
8882         case 2:
8883           {
8884             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8885             break;
8886           }
8887         case 1:
8888         case 0:
8889           {
8890             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8891             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8892             if(res.size()==2)
8893               {
8894                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8895               }
8896             else
8897               {
8898                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8899               }
8900             break;
8901           }
8902         default:
8903           {// case when plane is on a multi colinear edge of a polyhedron
8904             if((int)res.size()==2*nbOfSeg)
8905               {
8906                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8907               }
8908             else
8909               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8910           }
8911         }
8912     }
8913 }
8914
8915 /*!
8916  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8917  * 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).
8918  * 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
8919  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8920  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8921  * \param desc is the descending connectivity 3D->3DSurf
8922  * \param descIndx is the descending connectivity index 3D->3DSurf
8923  */
8924 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8925                                                   const int *desc, const int *descIndx,
8926                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8927 {
8928   checkFullyDefined();
8929   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8930     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8931   const int *nodal3D=_nodal_connec->getConstPointer();
8932   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8933   int nbOfCells=getNumberOfCells();
8934   for(int i=0;i<nbOfCells;i++)
8935     {
8936       std::map<int, std::set<int> > m;
8937       int offset=descIndx[i];
8938       int nbOfFaces=descIndx[i+1]-offset;
8939       int start=-1;
8940       int end=-1;
8941       for(int j=0;j<nbOfFaces;j++)
8942         {
8943           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8944           if(p.first!=-1 && p.second!=-1)
8945             {
8946               if(p.first!=-2)
8947                 {
8948                   start=p.first; end=p.second;
8949                   m[p.first].insert(p.second);
8950                   m[p.second].insert(p.first);
8951                 }
8952               else
8953                 {
8954                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8955                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8956                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8957                   INTERP_KERNEL::NormalizedCellType cmsId;
8958                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8959                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8960                   for(unsigned k=0;k<nbOfNodesSon;k++)
8961                     {
8962                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8963                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8964                     }
8965                 }
8966             }
8967         }
8968       if(m.empty())
8969         continue;
8970       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8971       int prev=end;
8972       while(end!=start)
8973         {
8974           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8975           const std::set<int>& s=(*it).second;
8976           std::set<int> s2; s2.insert(prev);
8977           std::set<int> s3;
8978           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8979           if(s3.size()==1)
8980             {
8981               int val=*s3.begin();
8982               conn.push_back(start);
8983               prev=start;
8984               start=val;
8985             }
8986           else
8987             start=end;
8988         }
8989       conn.push_back(end);
8990       if(conn.size()>3)
8991         {
8992           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8993           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8994           cellIds->pushBackSilent(i);
8995         }
8996     }
8997 }
8998
8999 /*!
9000  * 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
9001  * 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
9002  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
9003  * 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
9004  * 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.
9005  * 
9006  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
9007  */
9008 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
9009 {
9010   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
9011   if(sz>=4)
9012     {
9013       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
9014       if(cm.getDimension()==2)
9015         {
9016           const int *node=nodalConnBg+1;
9017           int startNode=*node++;
9018           double refX=coords[2*startNode];
9019           for(;node!=nodalConnEnd;node++)
9020             {
9021               if(coords[2*(*node)]<refX)
9022                 {
9023                   startNode=*node;
9024                   refX=coords[2*startNode];
9025                 }
9026             }
9027           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
9028           refX=1e300;
9029           double tmp1;
9030           double tmp2[2];
9031           double angle0=-M_PI/2;
9032           //
9033           int nextNode=-1;
9034           int prevNode=-1;
9035           double resRef;
9036           double angleNext=0.;
9037           while(nextNode!=startNode)
9038             {
9039               nextNode=-1;
9040               resRef=1e300;
9041               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
9042                 {
9043                   if(*node!=tmpOut.back() && *node!=prevNode)
9044                     {
9045                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
9046                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
9047                       double res;
9048                       if(angleM<=angle0)
9049                         res=angle0-angleM;
9050                       else
9051                         res=angle0-angleM+2.*M_PI;
9052                       if(res<resRef)
9053                         {
9054                           nextNode=*node;
9055                           resRef=res;
9056                           angleNext=angleM;
9057                         }
9058                     }
9059                 }
9060               if(nextNode!=startNode)
9061                 {
9062                   angle0=angleNext-M_PI;
9063                   if(angle0<-M_PI)
9064                     angle0+=2*M_PI;
9065                   prevNode=tmpOut.back();
9066                   tmpOut.push_back(nextNode);
9067                 }
9068             }
9069           std::vector<int> tmp3(2*(sz-1));
9070           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
9071           std::copy(nodalConnBg+1,nodalConnEnd,it);
9072           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
9073             {
9074               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9075               return false;
9076             }
9077           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
9078             {
9079               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9080               return false;
9081             }
9082           else
9083             {
9084               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
9085               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
9086               return true;
9087             }
9088         }
9089       else
9090         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9091     }
9092   else
9093     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9094 }
9095
9096 /*!
9097  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
9098  * 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.
9099  * 
9100  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
9101  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
9102  * \param [in,out] arr array in which the remove operation will be done.
9103  * \param [in,out] arrIndx array in the remove operation will modify
9104  * \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])
9105  * \return true if \b arr and \b arrIndx have been modified, false if not.
9106  */
9107 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
9108 {
9109   if(!arrIndx || !arr)
9110     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
9111   if(offsetForRemoval<0)
9112     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
9113   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
9114   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
9115   int *arrIPtr=arrIndx->getPointer();
9116   *arrIPtr++=0;
9117   int previousArrI=0;
9118   const int *arrPtr=arr->getConstPointer();
9119   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
9120   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
9121     {
9122       if(*arrIPtr-previousArrI>offsetForRemoval)
9123         {
9124           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
9125             {
9126               if(s.find(*work)==s.end())
9127                 arrOut.push_back(*work);
9128             }
9129         }
9130       previousArrI=*arrIPtr;
9131       *arrIPtr=(int)arrOut.size();
9132     }
9133   if(arr->getNumberOfTuples()==(int)arrOut.size())
9134     return false;
9135   arr->alloc((int)arrOut.size(),1);
9136   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
9137   return true;
9138 }
9139
9140 /*!
9141  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9142  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
9143  * The selection of extraction is done standardly in new2old format.
9144  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9145  *
9146  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9147  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9148  * \param [in] arrIn arr origin array from which the extraction will be done.
9149  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9150  * \param [out] arrOut the resulting array
9151  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9152  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
9153  */
9154 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9155                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9156 {
9157   if(!arrIn || !arrIndxIn)
9158     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
9159   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9160   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9161     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
9162   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
9163   const int *arrInPtr=arrIn->getConstPointer();
9164   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9165   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9166   if(nbOfGrps<0)
9167     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9168   int maxSizeOfArr=arrIn->getNumberOfTuples();
9169   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9170   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9171   arrIo->alloc((int)(sz+1),1);
9172   const int *idsIt=idsOfSelectBg;
9173   int *work=arrIo->getPointer();
9174   *work++=0;
9175   int lgth=0;
9176   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
9177     {
9178       if(*idsIt>=0 && *idsIt<nbOfGrps)
9179         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
9180       else
9181         {
9182           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9183           throw INTERP_KERNEL::Exception(oss.str().c_str());
9184         }
9185       if(lgth>=work[-1])
9186         *work=lgth;
9187       else
9188         {
9189           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
9190           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
9191           throw INTERP_KERNEL::Exception(oss.str().c_str());
9192         }
9193     }
9194   arro->alloc(lgth,1);
9195   work=arro->getPointer();
9196   idsIt=idsOfSelectBg;
9197   for(std::size_t i=0;i<sz;i++,idsIt++)
9198     {
9199       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
9200         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
9201       else
9202         {
9203           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
9204           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9205           throw INTERP_KERNEL::Exception(oss.str().c_str());
9206         }
9207     }
9208   arrOut=arro.retn();
9209   arrIndexOut=arrIo.retn();
9210 }
9211
9212 /*!
9213  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9214  * 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 ).
9215  * The selection of extraction is done standardly in new2old format.
9216  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9217  *
9218  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9219  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9220  * \param [in] arrIn arr origin array from which the extraction will be done.
9221  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9222  * \param [out] arrOut the resulting array
9223  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9224  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
9225  */
9226 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9227                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9228 {
9229   if(!arrIn || !arrIndxIn)
9230     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
9231   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9232   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9233     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
9234   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
9235   const int *arrInPtr=arrIn->getConstPointer();
9236   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9237   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9238   if(nbOfGrps<0)
9239     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9240   int maxSizeOfArr=arrIn->getNumberOfTuples();
9241   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9242   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9243   arrIo->alloc((int)(sz+1),1);
9244   int idsIt=idsOfSelectStart;
9245   int *work=arrIo->getPointer();
9246   *work++=0;
9247   int lgth=0;
9248   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
9249     {
9250       if(idsIt>=0 && idsIt<nbOfGrps)
9251         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
9252       else
9253         {
9254           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9255           throw INTERP_KERNEL::Exception(oss.str().c_str());
9256         }
9257       if(lgth>=work[-1])
9258         *work=lgth;
9259       else
9260         {
9261           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
9262           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
9263           throw INTERP_KERNEL::Exception(oss.str().c_str());
9264         }
9265     }
9266   arro->alloc(lgth,1);
9267   work=arro->getPointer();
9268   idsIt=idsOfSelectStart;
9269   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
9270     {
9271       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
9272         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
9273       else
9274         {
9275           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
9276           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9277           throw INTERP_KERNEL::Exception(oss.str().c_str());
9278         }
9279     }
9280   arrOut=arro.retn();
9281   arrIndexOut=arrIo.retn();
9282 }
9283
9284 /*!
9285  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9286  * 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
9287  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9288  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9289  *
9290  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9291  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9292  * \param [in] arrIn arr origin array from which the extraction will be done.
9293  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9294  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
9295  * \param [in] srcArrIndex index array of \b srcArr
9296  * \param [out] arrOut the resulting array
9297  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9298  * 
9299  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9300  */
9301 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9302                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9303                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9304 {
9305   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9306     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9308   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9309   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9310   std::vector<bool> v(nbOfTuples,true);
9311   int offset=0;
9312   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9313   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9314   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9315     {
9316       if(*it>=0 && *it<nbOfTuples)
9317         {
9318           v[*it]=false;
9319           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9320         }
9321       else
9322         {
9323           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9324           throw INTERP_KERNEL::Exception(oss.str().c_str());
9325         }
9326     }
9327   srcArrIndexPtr=srcArrIndex->getConstPointer();
9328   arrIo->alloc(nbOfTuples+1,1);
9329   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9330   const int *arrInPtr=arrIn->getConstPointer();
9331   const int *srcArrPtr=srcArr->getConstPointer();
9332   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9333   int *arroPtr=arro->getPointer();
9334   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9335     {
9336       if(v[ii])
9337         {
9338           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9339           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9340         }
9341       else
9342         {
9343           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9344           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9345           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9346         }
9347     }
9348   arrOut=arro.retn();
9349   arrIndexOut=arrIo.retn();
9350 }
9351
9352 /*!
9353  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9354  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9355  *
9356  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9357  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9358  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9359  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9360  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
9361  * \param [in] srcArrIndex index array of \b srcArr
9362  * 
9363  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9364  */
9365 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9366                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9367 {
9368   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9369     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9370   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9371   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9372   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9373   int *arrInOutPtr=arrInOut->getPointer();
9374   const int *srcArrPtr=srcArr->getConstPointer();
9375   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9376     {
9377       if(*it>=0 && *it<nbOfTuples)
9378         {
9379           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9380             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9381           else
9382             {
9383               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] !";
9384               throw INTERP_KERNEL::Exception(oss.str().c_str());
9385             }
9386         }
9387       else
9388         {
9389           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9390           throw INTERP_KERNEL::Exception(oss.str().c_str());
9391         }
9392     }
9393 }
9394
9395 /*!
9396  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9397  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9398  * 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]].
9399  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9400  * A negative value in \b arrIn means that it is ignored.
9401  * 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.
9402  * 
9403  * \param [in] arrIn arr origin array from which the extraction will be done.
9404  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9405  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9406  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9407  */
9408 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9409 {
9410   int seed=0,nbOfDepthPeelingPerformed=0;
9411   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9412 }
9413
9414 /*!
9415  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9416  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9417  * 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]].
9418  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9419  * A negative value in \b arrIn means that it is ignored.
9420  * 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.
9421  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9422  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9423  * \param [in] arrIn arr origin array from which the extraction will be done.
9424  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9425  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9426  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9427  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9428  * \sa MEDCouplingUMesh::partitionBySpreadZone
9429  */
9430 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9431 {
9432   nbOfDepthPeelingPerformed=0;
9433   if(!arrIndxIn)
9434     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9435   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9436   if(nbOfTuples<=0)
9437     {
9438       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9439       return ret;
9440     }
9441   //
9442   std::vector<bool> fetched(nbOfTuples,false);
9443   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9444 }
9445
9446 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9447 {
9448   nbOfDepthPeelingPerformed=0;
9449   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9450     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9451   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9452   std::vector<bool> fetched2(nbOfTuples,false);
9453   int i=0;
9454   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9455     {
9456       if(*seedElt>=0 && *seedElt<nbOfTuples)
9457         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9458       else
9459         { 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()); }
9460     }
9461   const int *arrInPtr=arrIn->getConstPointer();
9462   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9463   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9464   std::vector<int> idsToFetch1(seedBg,seedEnd);
9465   std::vector<int> idsToFetch2;
9466   std::vector<int> *idsToFetch=&idsToFetch1;
9467   std::vector<int> *idsToFetchOther=&idsToFetch2;
9468   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9469     {
9470       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9471         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9472           if(!fetched[*it2])
9473             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9474       std::swap(idsToFetch,idsToFetchOther);
9475       idsToFetchOther->clear();
9476       nbOfDepthPeelingPerformed++;
9477     }
9478   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9479   i=0;
9480   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9481   int *retPtr=ret->getPointer();
9482   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9483     if(*it)
9484       *retPtr++=i;
9485   return ret.retn();
9486 }
9487
9488 /*!
9489  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9490  * 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
9491  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9492  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9493  *
9494  * \param [in] start begin of set of ids of the input extraction (included)
9495  * \param [in] end end of set of ids of the input extraction (excluded)
9496  * \param [in] step step of the set of ids in range mode.
9497  * \param [in] arrIn arr origin array from which the extraction will be done.
9498  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9499  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9500  * \param [in] srcArrIndex index array of \b srcArr
9501  * \param [out] arrOut the resulting array
9502  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9503  * 
9504  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9505  */
9506 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9507                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9508                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9509 {
9510   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9511     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9512   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9513   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9514   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9515   int offset=0;
9516   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9517   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9518   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9519   int it=start;
9520   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9521     {
9522       if(it>=0 && it<nbOfTuples)
9523         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9524       else
9525         {
9526           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9527           throw INTERP_KERNEL::Exception(oss.str().c_str());
9528         }
9529     }
9530   srcArrIndexPtr=srcArrIndex->getConstPointer();
9531   arrIo->alloc(nbOfTuples+1,1);
9532   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9533   const int *arrInPtr=arrIn->getConstPointer();
9534   const int *srcArrPtr=srcArr->getConstPointer();
9535   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9536   int *arroPtr=arro->getPointer();
9537   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9538     {
9539       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9540       if(pos<0)
9541         {
9542           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9543           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9544         }
9545       else
9546         {
9547           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9548           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9549         }
9550     }
9551   arrOut=arro.retn();
9552   arrIndexOut=arrIo.retn();
9553 }
9554
9555 /*!
9556  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9557  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9558  *
9559  * \param [in] start begin of set of ids of the input extraction (included)
9560  * \param [in] end end of set of ids of the input extraction (excluded)
9561  * \param [in] step step of the set of ids in range mode.
9562  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9563  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9564  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9565  * \param [in] srcArrIndex index array of \b srcArr
9566  * 
9567  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9568  */
9569 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9570                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9571 {
9572   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9573     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9574   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9575   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9576   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9577   int *arrInOutPtr=arrInOut->getPointer();
9578   const int *srcArrPtr=srcArr->getConstPointer();
9579   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9580   int it=start;
9581   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9582     {
9583       if(it>=0 && it<nbOfTuples)
9584         {
9585           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9586             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9587           else
9588             {
9589               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9590               throw INTERP_KERNEL::Exception(oss.str().c_str());
9591             }
9592         }
9593       else
9594         {
9595           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9596           throw INTERP_KERNEL::Exception(oss.str().c_str());
9597         }
9598     }
9599 }
9600
9601 /*!
9602  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9603  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9604  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9605  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9606  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9607  * 
9608  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9609  */
9610 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
9611 {
9612   checkFullyDefined();
9613   int mdim=getMeshDimension();
9614   int spaceDim=getSpaceDimension();
9615   if(mdim!=spaceDim)
9616     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9617   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9618   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9619   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9620   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9621   ret->setCoords(getCoords());
9622   ret->allocateCells((int)partition.size());
9623   //
9624   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9625     {
9626       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9627       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9628       switch(mdim)
9629         {
9630         case 2:
9631           cell=tmp->buildUnionOf2DMesh();
9632           break;
9633         case 3:
9634           cell=tmp->buildUnionOf3DMesh();
9635           break;
9636         default:
9637           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9638         }
9639       
9640       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9641     }
9642   //
9643   ret->finishInsertingCells();
9644   return ret.retn();
9645 }
9646
9647 /*!
9648  * This method partitions \b this into contiguous zone.
9649  * This method only needs a well defined connectivity. Coordinates are not considered here.
9650  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9651  */
9652 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
9653 {
9654   int nbOfCellsCur=getNumberOfCells();
9655   std::vector<DataArrayInt *> ret;
9656   if(nbOfCellsCur<=0)
9657     return ret;
9658   DataArrayInt *neigh=0,*neighI=0;
9659   computeNeighborsOfCells(neigh,neighI);
9660   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9661   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9662   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9663   int seed=0;
9664   while(seed<nbOfCellsCur)
9665     {
9666       int nbOfPeelPerformed=0;
9667       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9668       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9669     }
9670   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9671     ret.push_back((*it).retn());
9672   return ret;
9673 }
9674
9675 /*!
9676  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9677  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9678  *
9679  * \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.
9680  * \return a newly allocated DataArrayInt to be managed by the caller.
9681  * \throw In case of \a code has not the right format (typically of size 3*n)
9682  */
9683 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
9684 {
9685   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9686   std::size_t nb=code.size()/3;
9687   if(code.size()%3!=0)
9688     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9689   ret->alloc((int)nb,2);
9690   int *retPtr=ret->getPointer();
9691   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9692     {
9693       retPtr[0]=code[3*i+2];
9694       retPtr[1]=code[3*i+2]+code[3*i+1];
9695     }
9696   return ret.retn();
9697 }
9698
9699 /*!
9700  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9701  * All cells in \a this are expected to be linear 3D cells.
9702  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9703  * It leads to an increase to number of cells.
9704  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9705  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
9706  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9707  *
9708  * \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.
9709  *                      For all other cells, the splitting policy will be ignored.
9710  * \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. 
9711  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9712  *          an id of old cell producing it. The caller is to delete this array using
9713  *         decrRef() as it is no more needed.
9714  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9715  *
9716  * \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
9717  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
9718  * 
9719  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9720  * \throw If \a this is not fully constituted with linear 3D cells.
9721  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
9722  */
9723 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
9724 {
9725   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9726   checkConnectivityFullyDefined();
9727   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9728     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9729   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9730   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
9731   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9732   int *retPt(ret->getPointer());
9733   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9734   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9735   const int *oldc(_nodal_connec->begin());
9736   const int *oldci(_nodal_connec_index->begin());
9737   const double *coords(_coords->begin());
9738   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9739     {
9740       std::vector<int> a; std::vector<double> b;
9741       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9742       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9743       const int *aa(&a[0]);
9744       if(!b.empty())
9745         {
9746           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9747             if(*it<0)
9748               *it=(-(*(it))-1+nbNodes);
9749           addPts->insertAtTheEnd(b.begin(),b.end());
9750           nbNodes+=(int)b.size()/3;
9751         }
9752       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9753         newConn->insertAtTheEnd(aa,aa+4);
9754     }
9755   if(!addPts->empty())
9756     {
9757       addPts->rearrange(3);
9758       nbOfAdditionalPoints=addPts->getNumberOfTuples();
9759       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9760       ret0->setCoords(addPts);
9761     }
9762   else
9763     {
9764       nbOfAdditionalPoints=0;
9765       ret0->setCoords(getCoords());
9766     }
9767   ret0->setNodalConnectivity(newConn);
9768   //
9769   ret->computeOffsets2();
9770   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
9771   return ret0.retn();
9772 }
9773
9774 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9775                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9776 {
9777   if(mesh)
9778     {
9779       mesh->incrRef();
9780       _nb_cell=mesh->getNumberOfCells();
9781     }
9782 }
9783
9784 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9785 {
9786   if(_mesh)
9787     _mesh->decrRef();
9788   if(_own_cell)
9789     delete _cell;
9790 }
9791
9792 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9793                                                                                                                                _own_cell(false),_cell_id(bg-1),
9794                                                                                                                                _nb_cell(end)
9795 {
9796   if(mesh)
9797     mesh->incrRef();
9798 }
9799
9800 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9801 {
9802   _cell_id++;
9803   if(_cell_id<_nb_cell)
9804     {
9805       _cell->next();
9806       return _cell;
9807     }
9808   else
9809     return 0;
9810 }
9811
9812 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9813 {
9814   if(_mesh)
9815     _mesh->incrRef();
9816 }
9817
9818 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9819 {
9820   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9821 }
9822
9823 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9824 {
9825   if(_mesh)
9826     _mesh->decrRef();
9827 }
9828
9829 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9830                                                                                                                                                                   _itc(itc),
9831                                                                                                                                                                   _bg(bg),_end(end)
9832 {
9833   if(_mesh)
9834     _mesh->incrRef();
9835 }
9836
9837 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9838 {
9839   if(_mesh)
9840     _mesh->decrRef();
9841 }
9842
9843 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9844 {
9845   return _type;
9846 }
9847
9848 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9849 {
9850   return _end-_bg;
9851 }
9852
9853 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9854 {
9855   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9856 }
9857
9858 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9859 {
9860   if(mesh)
9861     {
9862       mesh->incrRef();
9863       _nb_cell=mesh->getNumberOfCells();
9864     }
9865 }
9866
9867 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9868 {
9869   if(_mesh)
9870     _mesh->decrRef();
9871   delete _cell;
9872 }
9873
9874 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9875 {
9876   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9877   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9878   if(_cell_id<_nb_cell)
9879     {
9880       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9881       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9882       int startId=_cell_id;
9883       _cell_id+=nbOfElems;
9884       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9885     }
9886   else
9887     return 0;
9888 }
9889
9890 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9891 {
9892   if(mesh)
9893     {
9894       _conn=mesh->getNodalConnectivity()->getPointer();
9895       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9896     }
9897 }
9898
9899 void MEDCouplingUMeshCell::next()
9900 {
9901   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9902     {
9903       _conn+=_conn_lgth;
9904       _conn_indx++;
9905     }
9906   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9907 }
9908
9909 std::string MEDCouplingUMeshCell::repr() const
9910 {
9911   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9912     {
9913       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9914       oss << " : ";
9915       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9916       return oss.str();
9917     }
9918   else
9919     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9920 }
9921
9922 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9923 {
9924   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9925     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9926   else
9927     return INTERP_KERNEL::NORM_ERROR;
9928 }
9929
9930 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9931 {
9932   lgth=_conn_lgth;
9933   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9934     return _conn;
9935   else
9936     return 0;
9937 }