Salome HOME
Merge branch 'master' of ssh://git.salome-platform.org/modules/med
[modules/med.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
42
43 #include <sstream>
44 #include <fstream>
45 #include <numeric>
46 #include <cstring>
47 #include <limits>
48 #include <list>
49
50 using namespace ParaMEDMEM;
51
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53
54 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
55
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 {
58   return new MEDCouplingUMesh;
59 }
60
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
62 {
63   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64   ret->setName(meshName);
65   ret->setMeshDimension(meshDim);
66   return ret;
67 }
68
69 /*!
70  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71  * between \a this and the new mesh.
72  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73  *          delete this mesh using decrRef() as it is no more needed. 
74  */
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
76 {
77   return clone(true);
78 }
79
80 /*!
81  * Returns a new MEDCouplingMesh which is a copy of \a this one.
82  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83  * this mesh are shared by the new mesh.
84  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85  *          delete this mesh using decrRef() as it is no more needed. 
86  */
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
88 {
89   return new MEDCouplingUMesh(*this,recDeepCpy);
90 }
91
92 /*!
93  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94  * The coordinates are shared between \a this and the returned instance.
95  * 
96  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97  * \sa MEDCouplingUMesh::deepCpy
98  */
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
100 {
101   checkConnectivityFullyDefined();
102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104   ret->setConnectivity(c,ci);
105   return ret.retn();
106 }
107
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
109 {
110   if(!other)
111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
113   if(!otherC)
114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
117 }
118
119 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
120 {
121   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
122   return ret;
123 }
124
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildren() const
126 {
127   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildren());
128   if(_nodal_connec)
129     ret.push_back(_nodal_connec);
130   if(_nodal_connec_index)
131     ret.push_back(_nodal_connec_index);
132   return ret;
133 }
134
135 void MEDCouplingUMesh::updateTime() const
136 {
137   MEDCouplingPointSet::updateTime();
138   if(_nodal_connec)
139     {
140       updateTimeWith(*_nodal_connec);
141     }
142   if(_nodal_connec_index)
143     {
144       updateTimeWith(*_nodal_connec_index);
145     }
146 }
147
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
149 {
150 }
151
152 /*!
153  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154  * then \a this mesh is most probably is writable, exchangeable and available for most
155  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156  * this method to check that all is in order with \a this mesh.
157  *  \throw If the mesh dimension is not set.
158  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
159  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160  *  \throw If the connectivity data array has more than one component.
161  *  \throw If the connectivity data array has a named component.
162  *  \throw If the connectivity index data array has more than one component.
163  *  \throw If the connectivity index data array has a named component.
164  */
165 void MEDCouplingUMesh::checkCoherency() const
166 {
167   if(_mesh_dim<-1)
168    throw INTERP_KERNEL::Exception("No mesh dimension specified !");
169   if(_mesh_dim!=-1)
170     MEDCouplingPointSet::checkCoherency();
171   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
172     {
173       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
174         {
175           std::ostringstream message;
176           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177           throw INTERP_KERNEL::Exception(message.str().c_str());
178         }
179     }
180   if(_nodal_connec)
181     {
182       if(_nodal_connec->getNumberOfComponents()!=1)
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184       if(_nodal_connec->getInfoOnComponent(0)!="")
185         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
186     }
187   else
188     if(_mesh_dim!=-1)
189       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190   if(_nodal_connec_index)
191     {
192       if(_nodal_connec_index->getNumberOfComponents()!=1)
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194       if(_nodal_connec_index->getInfoOnComponent(0)!="")
195         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
196     }
197   else
198     if(_mesh_dim!=-1)
199       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
200 }
201
202 /*!
203  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204  * then \a this mesh is most probably is writable, exchangeable and available for all
205  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206  * method thoroughly checks the nodal connectivity.
207  *  \param [in] eps - a not used parameter.
208  *  \throw If the mesh dimension is not set.
209  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
210  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211  *  \throw If the connectivity data array has more than one component.
212  *  \throw If the connectivity data array has a named component.
213  *  \throw If the connectivity index data array has more than one component.
214  *  \throw If the connectivity index data array has a named component.
215  *  \throw If number of nodes defining an element does not correspond to the type of element.
216  *  \throw If the nodal connectivity includes an invalid node id.
217  */
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
219 {
220   checkCoherency();
221   if(_mesh_dim==-1)
222     return ;
223   int meshDim=getMeshDimension();
224   int nbOfNodes=getNumberOfNodes();
225   int nbOfCells=getNumberOfCells();
226   const int *ptr=_nodal_connec->getConstPointer();
227   const int *ptrI=_nodal_connec_index->getConstPointer();
228   for(int i=0;i<nbOfCells;i++)
229     {
230       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231       if((int)cm.getDimension()!=meshDim)
232         {
233           std::ostringstream oss;
234           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235           throw INTERP_KERNEL::Exception(oss.str().c_str());
236         }
237       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
238       if(!cm.isDynamic())
239         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
240           {
241             std::ostringstream oss;
242             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
243             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244             throw INTERP_KERNEL::Exception(oss.str().c_str());
245           }
246       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
247         {
248           int nodeId=*w;
249           if(nodeId>=0)
250             {
251               if(nodeId>=nbOfNodes)
252                 {
253                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
254                   throw INTERP_KERNEL::Exception(oss.str().c_str());
255                 }
256             }
257           else if(nodeId<-1)
258             {
259               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
260               throw INTERP_KERNEL::Exception(oss.str().c_str());
261             }
262           else
263             {
264               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
265                 {
266                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
267                   throw INTERP_KERNEL::Exception(oss.str().c_str());
268                 }
269             }
270         }
271     }
272 }
273
274
275 /*!
276  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
277  * then \a this mesh is most probably is writable, exchangeable and available for all
278  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
279  *  \param [in] eps - a not used parameter.
280  *  \throw If the mesh dimension is not set.
281  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
282  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
283  *  \throw If the connectivity data array has more than one component.
284  *  \throw If the connectivity data array has a named component.
285  *  \throw If the connectivity index data array has more than one component.
286  *  \throw If the connectivity index data array has a named component.
287  *  \throw If number of nodes defining an element does not correspond to the type of element.
288  *  \throw If the nodal connectivity includes an invalid node id.
289  */
290 void MEDCouplingUMesh::checkCoherency2(double eps) const
291 {
292   checkCoherency1(eps);
293 }
294
295 /*!
296  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
297  * elements contained in the mesh. For more info on the mesh dimension see
298  * \ref MEDCouplingUMeshPage.
299  *  \param [in] meshDim - a new mesh dimension.
300  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
301  */
302 void MEDCouplingUMesh::setMeshDimension(int meshDim)
303 {
304   if(meshDim<-1 || meshDim>3)
305     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
306   _mesh_dim=meshDim;
307   declareAsNew();
308 }
309
310 /*!
311  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
312  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
313  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
314  *
315  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
316  *
317  *  \if ENABLE_EXAMPLES
318  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
319  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
320  *  \endif
321  */
322 void MEDCouplingUMesh::allocateCells(int nbOfCells)
323 {
324   if(nbOfCells<0)
325     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
326   if(_nodal_connec_index)
327     {
328       _nodal_connec_index->decrRef();
329     }
330   if(_nodal_connec)
331     {
332       _nodal_connec->decrRef();
333     }
334   _nodal_connec_index=DataArrayInt::New();
335   _nodal_connec_index->reserve(nbOfCells+1);
336   _nodal_connec_index->pushBackSilent(0);
337   _nodal_connec=DataArrayInt::New();
338   _nodal_connec->reserve(2*nbOfCells);
339   _types.clear();
340   declareAsNew();
341 }
342
343 /*!
344  * Appends a cell to the connectivity array. For deeper understanding what is
345  * happening see \ref MEDCouplingUMeshNodalConnectivity.
346  *  \param [in] type - type of cell to add.
347  *  \param [in] size - number of nodes constituting this cell.
348  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
349  * 
350  *  \if ENABLE_EXAMPLES
351  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
352  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
353  *  \endif
354  */
355 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
356 {
357   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
358   if(_nodal_connec_index==0)
359     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
360   if((int)cm.getDimension()==_mesh_dim)
361     {
362       if(!cm.isDynamic())
363         if(size!=(int)cm.getNumberOfNodes())
364           {
365             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
366             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
367             throw INTERP_KERNEL::Exception(oss.str().c_str());
368           }
369       int idx=_nodal_connec_index->back();
370       int val=idx+size+1;
371       _nodal_connec_index->pushBackSilent(val);
372       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
373       _types.insert(type);
374     }
375   else
376     {
377       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
378       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
379       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
380       throw INTERP_KERNEL::Exception(oss.str().c_str());
381     }
382 }
383
384 /*!
385  * Compacts data arrays to release unused memory. This method is to be called after
386  * finishing cell insertion using \a this->insertNextCell().
387  * 
388  *  \if ENABLE_EXAMPLES
389  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
390  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
391  *  \endif
392  */
393 void MEDCouplingUMesh::finishInsertingCells()
394 {
395   _nodal_connec->pack();
396   _nodal_connec_index->pack();
397   _nodal_connec->declareAsNew();
398   _nodal_connec_index->declareAsNew();
399   updateTime();
400 }
401
402 /*!
403  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
404  * Useful for python users.
405  */
406 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
407 {
408   return new MEDCouplingUMeshCellIterator(this);
409 }
410
411 /*!
412  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
413  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
414  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
415  * Useful for python users.
416  */
417 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
418 {
419   if(!checkConsecutiveCellTypes())
420     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
421   return new MEDCouplingUMeshCellByTypeEntry(this);
422 }
423
424 /*!
425  * Returns a set of all cell types available in \a this mesh.
426  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
427  * \warning this method does not throw any exception even if \a this is not defined.
428  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
429  */
430 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
431 {
432   return _types;
433 }
434
435 /*!
436  * This method returns the sorted list of geometric types in \a this.
437  * 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
438  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
439  *
440  * \throw if connectivity in \a this is not correctly defined.
441  *  
442  * \sa MEDCouplingMesh::getAllGeoTypes
443  */
444 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
445 {
446   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
447   checkConnectivityFullyDefined();
448   int nbOfCells(getNumberOfCells());
449   if(nbOfCells==0)
450     return ret;
451   if(getMeshLength()<1)
452     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
453   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
454   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
455   for(int i=1;i<nbOfCells;i++,ci++)
456     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
457       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
458   return ret;
459 }
460
461 /*!
462  * This method is a method that compares \a this and \a other.
463  * This method compares \b all attributes, even names and component names.
464  */
465 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
466 {
467   if(!other)
468     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
469   std::ostringstream oss; oss.precision(15);
470   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
471   if(!otherC)
472     {
473       reason="mesh given in input is not castable in MEDCouplingUMesh !";
474       return false;
475     }
476   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
477     return false;
478   if(_mesh_dim!=otherC->_mesh_dim)
479     {
480       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
481       reason=oss.str();
482       return false;
483     }
484   if(_types!=otherC->_types)
485     {
486       oss << "umesh geometric type mismatch :\nThis geometric types are :";
487       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
488         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
489       oss << "\nOther geometric types are :";
490       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
491         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
492       reason=oss.str();
493       return false;
494     }
495   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
496     if(_nodal_connec==0 || otherC->_nodal_connec==0)
497       {
498         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
499         return false;
500       }
501   if(_nodal_connec!=otherC->_nodal_connec)
502     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
503       {
504         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
505         return false;
506       }
507   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
508     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
509       {
510         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
511         return false;
512       }
513   if(_nodal_connec_index!=otherC->_nodal_connec_index)
514     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
515       {
516         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
517         return false;
518       }
519   return true;
520 }
521
522 /*!
523  * Checks if data arrays of this mesh (node coordinates, nodal
524  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
525  * not considered.
526  *  \param [in] other - the mesh to compare with.
527  *  \param [in] prec - precision value used to compare node coordinates.
528  *  \return bool - \a true if the two meshes are same.
529  */
530 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
531 {
532   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
533   if(!otherC)
534     return false;
535   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
536     return false;
537   if(_mesh_dim!=otherC->_mesh_dim)
538     return false;
539   if(_types!=otherC->_types)
540     return false;
541   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
542     if(_nodal_connec==0 || otherC->_nodal_connec==0)
543       return false;
544   if(_nodal_connec!=otherC->_nodal_connec)
545     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
546       return false;
547   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
548     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
549       return false;
550   if(_nodal_connec_index!=otherC->_nodal_connec_index)
551     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
552       return false;
553   return true;
554 }
555
556 /*!
557  * Checks if \a this and \a other meshes are geometrically equivalent with high
558  * probability, else an exception is thrown. The meshes are considered equivalent if
559  * (1) meshes contain the same number of nodes and the same number of elements of the
560  * same types (2) three cells of the two meshes (first, last and middle) are based
561  * on coincident nodes (with a specified precision).
562  *  \param [in] other - the mesh to compare with.
563  *  \param [in] prec - the precision used to compare nodes of the two meshes.
564  *  \throw If the two meshes do not match.
565  */
566 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
567 {
568  MEDCouplingPointSet::checkFastEquivalWith(other,prec);
569  const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
570   if(!otherC)
571     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
572 }
573
574 /*!
575  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
576  * cells each node belongs to.
577  * \warning For speed reasons, this method does not check if node ids in the nodal
578  *          connectivity correspond to the size of node coordinates array.
579  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
580  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
581  *        dividing cell ids in \a revNodal into groups each referring to one
582  *        node. Its every element (except the last one) is an index pointing to the
583  *         first id of a group of cells. For example cells sharing the node #1 are 
584  *        described by following range of indices: 
585  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
586  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
587  *        Number of cells sharing the *i*-th node is
588  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
589  * \throw If the coordinates array is not set.
590  * \throw If the nodal connectivity of cells is not defined.
591  * 
592  * \if ENABLE_EXAMPLES
593  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
594  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
595  * \endif
596  */
597 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
598 {
599   checkFullyDefined();
600   int nbOfNodes=getNumberOfNodes();
601   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
602   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
603   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
604   const int *conn=_nodal_connec->getConstPointer();
605   const int *connIndex=_nodal_connec_index->getConstPointer();
606   int nbOfCells=getNumberOfCells();
607   int nbOfEltsInRevNodal=0;
608   for(int eltId=0;eltId<nbOfCells;eltId++)
609     {
610       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
611       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
612       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
613         if(*iter>=0)//for polyhedrons
614           {
615             nbOfEltsInRevNodal++;
616             revNodalIndxPtr[(*iter)+1]++;
617           }
618     }
619   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
620   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
621   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
622   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
623   for(int eltId=0;eltId<nbOfCells;eltId++)
624     {
625       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
626       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
627       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
628         if(*iter>=0)//for polyhedrons
629           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
630     }
631 }
632
633 /// @cond INTERNAL
634
635 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
636 {
637   return id;
638 }
639
640 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
641 {
642   if(!compute)
643     return id+1;
644   else
645     {
646       if(cm.getOrientationStatus(nb,conn1,conn2))
647         return id+1;
648       else
649         return -(id+1);
650     }
651 }
652
653 class MinusOneSonsGenerator
654 {
655 public:
656   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
657   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
658   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
659   static const int DELTA=1;
660 private:
661   const INTERP_KERNEL::CellModel& _cm;
662 };
663
664 class MinusOneSonsGeneratorBiQuadratic
665 {
666 public:
667   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
668   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
669   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
670   static const int DELTA=1;
671 private:
672   const INTERP_KERNEL::CellModel& _cm;
673 };
674
675 class MinusTwoSonsGenerator
676 {
677 public:
678   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
679   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
680   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
681   static const int DELTA=2;
682 private:
683   const INTERP_KERNEL::CellModel& _cm;
684 };
685
686 /// @endcond
687
688 /*!
689  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
690  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
691  * describing correspondence between cells of \a this and the result meshes are
692  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
693  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
694  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
695  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
696  * \warning For speed reasons, this method does not check if node ids in the nodal
697  *          connectivity correspond to the size of node coordinates array.
698  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
699  *          to write this mesh to the MED file, its cells must be sorted using
700  *          sortCellsInMEDFileFrmt().
701  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
702  *         each cell of \a this mesh.
703  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
704  *        dividing cell ids in \a desc into groups each referring to one
705  *        cell of \a this mesh. Its every element (except the last one) is an index
706  *        pointing to the first id of a group of cells. For example cells of the
707  *        result mesh bounding the cell #1 of \a this mesh are described by following
708  *        range of indices:
709  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
710  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
711  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
712  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
713  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
714  *         by each cell of the result mesh.
715  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
716  *        in the result mesh,
717  *        dividing cell ids in \a revDesc into groups each referring to one
718  *        cell of the result mesh the same way as \a descIndx divides \a desc.
719  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
720  *        delete this mesh using decrRef() as it is no more needed.
721  *  \throw If the coordinates array is not set.
722  *  \throw If the nodal connectivity of cells is node defined.
723  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
724  *         revDescIndx == NULL.
725  * 
726  *  \if ENABLE_EXAMPLES
727  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
728  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
729  *  \endif
730  * \sa buildDescendingConnectivity2()
731  */
732 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
733 {
734   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
735 }
736
737 /*!
738  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
739  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
740  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
741  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
742  * \sa MEDCouplingUMesh::buildDescendingConnectivity
743  */
744 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
745 {
746   checkFullyDefined();
747   if(getMeshDimension()!=3)
748     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
749   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
750 }
751
752 /*!
753  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
754  * this->getMeshDimension(), that bound cells of \a this mesh. In
755  * addition arrays describing correspondence between cells of \a this and the result
756  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
757  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
758  *  mesh. This method differs from buildDescendingConnectivity() in that apart
759  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
760  * result meshes. So a positive id means that order of nodes in corresponding cells
761  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
762  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
763  * i.e. cell ids are one-based.
764  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
765  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
766  * \warning For speed reasons, this method does not check if node ids in the nodal
767  *          connectivity correspond to the size of node coordinates array.
768  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
769  *          to write this mesh to the MED file, its cells must be sorted using
770  *          sortCellsInMEDFileFrmt().
771  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
772  *         each cell of \a this mesh.
773  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
774  *        dividing cell ids in \a desc into groups each referring to one
775  *        cell of \a this mesh. Its every element (except the last one) is an index
776  *        pointing to the first id of a group of cells. For example cells of the
777  *        result mesh bounding the cell #1 of \a this mesh are described by following
778  *        range of indices:
779  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
780  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
781  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
782  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
783  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
784  *         by each cell of the result mesh.
785  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
786  *        in the result mesh,
787  *        dividing cell ids in \a revDesc into groups each referring to one
788  *        cell of the result mesh the same way as \a descIndx divides \a desc.
789  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
790  *        shares the node coordinates array with \a this mesh. The caller is to
791  *        delete this mesh using decrRef() as it is no more needed.
792  *  \throw If the coordinates array is not set.
793  *  \throw If the nodal connectivity of cells is node defined.
794  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
795  *         revDescIndx == NULL.
796  * 
797  *  \if ENABLE_EXAMPLES
798  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
799  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
800  *  \endif
801  * \sa buildDescendingConnectivity()
802  */
803 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
804 {
805   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
806 }
807
808 /*!
809  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
810  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
811  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
812  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
813  *
814  * \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
815  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
816  * \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.
817  */
818 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
819 {
820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
823   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
824   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
825   meshDM1=0;
826   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
827 }
828
829 /*!
830  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
831  * 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,
832  * excluding a set of meshdim-1 cells in input descending connectivity.
833  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
834  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
835  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
836  *
837  * \param [in] desc descending connectivity array.
838  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
839  * \param [in] revDesc reverse descending connectivity array.
840  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
841  * \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
842  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
843  * \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.
844  */
845 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
846                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
847 {
848   if(!desc || !descIndx || !revDesc || !revDescIndx)
849     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
850   const int *descPtr=desc->getConstPointer();
851   const int *descIPtr=descIndx->getConstPointer();
852   const int *revDescPtr=revDesc->getConstPointer();
853   const int *revDescIPtr=revDescIndx->getConstPointer();
854   //
855   int nbCells=descIndx->getNumberOfTuples()-1;
856   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
857   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
858   int *out1Ptr=out1->getPointer();
859   *out1Ptr++=0;
860   out0->reserve(desc->getNumberOfTuples());
861   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
862     {
863       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
864         {
865           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
866           s.erase(i);
867           out0->insertAtTheEnd(s.begin(),s.end());
868         }
869       *out1Ptr=out0->getNumberOfTuples();
870     }
871   neighbors=out0.retn();
872   neighborsIndx=out1.retn();
873 }
874
875 /// @cond INTERNAL
876
877 /*!
878  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
879  * For speed reasons no check of this will be done.
880  */
881 template<class SonsGenerator>
882 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
883 {
884   if(!desc || !descIndx || !revDesc || !revDescIndx)
885     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
886   checkConnectivityFullyDefined();
887   int nbOfCells=getNumberOfCells();
888   int nbOfNodes=getNumberOfNodes();
889   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
890   int *revNodalIndxPtr=revNodalIndx->getPointer();
891   const int *conn=_nodal_connec->getConstPointer();
892   const int *connIndex=_nodal_connec_index->getConstPointer();
893   std::string name="Mesh constituent of "; name+=getName();
894   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
895   ret->setCoords(getCoords());
896   ret->allocateCells(2*nbOfCells);
897   descIndx->alloc(nbOfCells+1,1);
898   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
899   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
900   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
901     {
902       int pos=connIndex[eltId];
903       int posP1=connIndex[eltId+1];
904       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
905       SonsGenerator sg(cm);
906       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
907       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
908       for(unsigned i=0;i<nbOfSons;i++)
909         {
910           INTERP_KERNEL::NormalizedCellType cmsId;
911           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
912           for(unsigned k=0;k<nbOfNodesSon;k++)
913             if(tmp[k]>=0)
914               revNodalIndxPtr[tmp[k]+1]++;
915           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
916           revDesc2->pushBackSilent(eltId);
917         }
918       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
919     }
920   int nbOfCellsM1=ret->getNumberOfCells();
921   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
922   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
923   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
924   int *revNodalPtr=revNodal->getPointer();
925   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
926   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
927   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
928     {
929       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
930       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
931       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
932         if(*iter>=0)//for polyhedrons
933           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
934     }
935   //
936   DataArrayInt *commonCells=0,*commonCellsI=0;
937   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
938   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
939   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
940   int newNbOfCellsM1=-1;
941   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
942                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
943   std::vector<bool> isImpacted(nbOfCellsM1,false);
944   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
945     for(int work2=work[0];work2!=work[1];work2++)
946       isImpacted[commonCellsPtr[work2]]=true;
947   const int *o2nM1Ptr=o2nM1->getConstPointer();
948   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
949   const int *n2oM1Ptr=n2oM1->getConstPointer();
950   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
951   ret2->copyTinyInfoFrom(this);
952   desc->alloc(descIndx->back(),1);
953   int *descPtr=desc->getPointer();
954   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
955   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
956     {
957       if(!isImpacted[i])
958         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
959       else
960         {
961           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
962             {
963               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
964               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
965             }
966           else
967             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
968         }
969     }
970   revDesc->reserve(newNbOfCellsM1);
971   revDescIndx->alloc(newNbOfCellsM1+1,1);
972   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
973   const int *revDesc2Ptr=revDesc2->getConstPointer();
974   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
975     {
976       int oldCellIdM1=n2oM1Ptr[i];
977       if(!isImpacted[oldCellIdM1])
978         {
979           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
980           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
981         }
982       else
983         {
984           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
985             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
986           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
987           commonCellsIPtr++;
988         }
989     }
990   //
991   return ret2.retn();
992 }
993
994 struct MEDCouplingAccVisit
995 {
996   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
997   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
998   int _new_nb_of_nodes;
999 };
1000
1001 /// @endcond
1002
1003 /*!
1004  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1005  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1006  * array of cell ids. Pay attention that after conversion all algorithms work slower
1007  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1008  * conversion due presence of invalid ids in the array of cells to convert, as a
1009  * result \a this mesh contains some already converted elements. In this case the 2D
1010  * mesh remains valid but 3D mesh becomes \b inconsistent!
1011  *  \warning This method can significantly modify the order of geometric types in \a this,
1012  *          hence, to write this mesh to the MED file, its cells must be sorted using
1013  *          sortCellsInMEDFileFrmt().
1014  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1015  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1016  *         cellIdsToConvertBg.
1017  *  \throw If the coordinates array is not set.
1018  *  \throw If the nodal connectivity of cells is node defined.
1019  *  \throw If dimension of \a this mesh is not either 2 or 3.
1020  *
1021  *  \if ENABLE_EXAMPLES
1022  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1023  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1024  *  \endif
1025  */
1026 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1027 {
1028   checkFullyDefined();
1029   int dim=getMeshDimension();
1030   if(dim<2 || dim>3)
1031     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1032   int nbOfCells(getNumberOfCells());
1033   if(dim==2)
1034     {
1035       const int *connIndex=_nodal_connec_index->getConstPointer();
1036       int *conn=_nodal_connec->getPointer();
1037       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1038         {
1039           if(*iter>=0 && *iter<nbOfCells)
1040             {
1041               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1042               if(!cm.isQuadratic())
1043                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1044               else
1045                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1046             }
1047           else
1048             {
1049               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1050               oss << " in range [0," << nbOfCells << ") !";
1051               throw INTERP_KERNEL::Exception(oss.str().c_str());
1052             }
1053         }
1054     }
1055   else
1056     {
1057       int *connIndex(_nodal_connec_index->getPointer());
1058       const int *connOld(_nodal_connec->getConstPointer());
1059       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1060       std::vector<bool> toBeDone(nbOfCells,false);
1061       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1062         {
1063           if(*iter>=0 && *iter<nbOfCells)
1064             toBeDone[*iter]=true;
1065           else
1066             {
1067               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1068               oss << " in range [0," << nbOfCells << ") !";
1069               throw INTERP_KERNEL::Exception(oss.str().c_str());
1070             }
1071         }
1072       for(int cellId=0;cellId<nbOfCells;cellId++)
1073         {
1074           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1075           int lgthOld(posP1-pos-1);
1076           if(toBeDone[cellId])
1077             {
1078               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1079               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1080               int *tmp(new int[nbOfFaces*lgthOld+1]);
1081               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1082               for(unsigned j=0;j<nbOfFaces;j++)
1083                 {
1084                   INTERP_KERNEL::NormalizedCellType type;
1085                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1086                   work+=offset;
1087                   *work++=-1;
1088                 }
1089               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1090               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1091               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1092               delete [] tmp;
1093             }
1094           else
1095             {
1096               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1097               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1098             }
1099         }
1100       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1101     }
1102   computeTypes();
1103 }
1104
1105 /*!
1106  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1107  * polyhedrons (if \a this is a 3D mesh).
1108  *  \warning As this method is purely for user-friendliness and no optimization is
1109  *          done to avoid construction of a useless vector, this method can be costly
1110  *          in memory.
1111  *  \throw If the coordinates array is not set.
1112  *  \throw If the nodal connectivity of cells is node defined.
1113  *  \throw If dimension of \a this mesh is not either 2 or 3.
1114  */
1115 void MEDCouplingUMesh::convertAllToPoly()
1116 {
1117   int nbOfCells=getNumberOfCells();
1118   std::vector<int> cellIds(nbOfCells);
1119   for(int i=0;i<nbOfCells;i++)
1120     cellIds[i]=i;
1121   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1122 }
1123
1124 /*!
1125  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1126  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1127  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1128  * base facet of the volume and the second half of nodes describes an opposite facet
1129  * having the same number of nodes as the base one. This method converts such
1130  * connectivity to a valid polyhedral format where connectivity of each facet is
1131  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1132  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1133  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1134  * a correct orientation of the first facet of a polyhedron, else orientation of a
1135  * corrected cell is reverse.<br>
1136  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1137  * it releases the user from boring description of polyhedra connectivity in the valid
1138  * format.
1139  *  \throw If \a this->getMeshDimension() != 3.
1140  *  \throw If \a this->getSpaceDimension() != 3.
1141  *  \throw If the nodal connectivity of cells is not defined.
1142  *  \throw If the coordinates array is not set.
1143  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1144  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1145  *
1146  *  \if ENABLE_EXAMPLES
1147  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1148  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1149  *  \endif
1150  */
1151 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1152 {
1153   checkFullyDefined();
1154   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1155     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1156   int nbOfCells=getNumberOfCells();
1157   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1158   newCi->alloc(nbOfCells+1,1);
1159   int *newci=newCi->getPointer();
1160   const int *ci=_nodal_connec_index->getConstPointer();
1161   const int *c=_nodal_connec->getConstPointer();
1162   newci[0]=0;
1163   for(int i=0;i<nbOfCells;i++)
1164     {
1165       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1166       if(type==INTERP_KERNEL::NORM_POLYHED)
1167         {
1168           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1169             {
1170               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1171               throw INTERP_KERNEL::Exception(oss.str().c_str());
1172             }
1173           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1174           if(n2%2!=0)
1175             {
1176               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 !";
1177               throw INTERP_KERNEL::Exception(oss.str().c_str());
1178             }
1179           int n1=(int)(n2/2);
1180           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)
1181         }
1182       else
1183         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1184     }
1185   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1186   newC->alloc(newci[nbOfCells],1);
1187   int *newc=newC->getPointer();
1188   for(int i=0;i<nbOfCells;i++)
1189     {
1190       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1191       if(type==INTERP_KERNEL::NORM_POLYHED)
1192         {
1193           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1194           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1195           *newc++=-1;
1196           for(std::size_t j=0;j<n1;j++)
1197             {
1198               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1199               newc[n1+5*j]=-1;
1200               newc[n1+5*j+1]=c[ci[i]+1+j];
1201               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1202               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1203               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1204             }
1205           newc+=n1*6;
1206         }
1207       else
1208         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1209     }
1210   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1211   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1212 }
1213
1214
1215 /*!
1216  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1217  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1218  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1219  *          to write this mesh to the MED file, its cells must be sorted using
1220  *          sortCellsInMEDFileFrmt().
1221  * \return \c true if at least one cell has been converted, \c false else. In the
1222  *         last case the nodal connectivity remains unchanged.
1223  * \throw If the coordinates array is not set.
1224  * \throw If the nodal connectivity of cells is not defined.
1225  * \throw If \a this->getMeshDimension() < 0.
1226  */
1227 bool MEDCouplingUMesh::unPolyze()
1228 {
1229   checkFullyDefined();
1230   int mdim=getMeshDimension();
1231   if(mdim<0)
1232     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1233   if(mdim<=1)
1234     return false;
1235   int nbOfCells=getNumberOfCells();
1236   if(nbOfCells<1)
1237     return false;
1238   int initMeshLgth=getMeshLength();
1239   int *conn=_nodal_connec->getPointer();
1240   int *index=_nodal_connec_index->getPointer();
1241   int posOfCurCell=0;
1242   int newPos=0;
1243   int lgthOfCurCell;
1244   bool ret=false;
1245   for(int i=0;i<nbOfCells;i++)
1246     {
1247       lgthOfCurCell=index[i+1]-posOfCurCell;
1248       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1249       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1250       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1251       int newLgth;
1252       if(cm.isDynamic())
1253         {
1254           switch(cm.getDimension())
1255             {
1256             case 2:
1257               {
1258                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1259                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1260                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1261                 break;
1262               }
1263             case 3:
1264               {
1265                 int nbOfFaces,lgthOfPolyhConn;
1266                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1267                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1268                 break;
1269               }
1270             case 1:
1271               {
1272                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1273                 break;
1274               }
1275             }
1276           ret=ret || (newType!=type);
1277           conn[newPos]=newType;
1278           newPos+=newLgth+1;
1279           posOfCurCell=index[i+1];
1280           index[i+1]=newPos;
1281         }
1282       else
1283         {
1284           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1285           newPos+=lgthOfCurCell;
1286           posOfCurCell+=lgthOfCurCell;
1287           index[i+1]=newPos;
1288         }
1289     }
1290   if(newPos!=initMeshLgth)
1291     _nodal_connec->reAlloc(newPos);
1292   if(ret)
1293     computeTypes();
1294   return ret;
1295 }
1296
1297 /*!
1298  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1299  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1300  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1301  *
1302  * \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 
1303  *             precision.
1304  */
1305 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1306 {
1307   checkFullyDefined();
1308   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1309     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1310   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1311   coords->recenterForMaxPrecision(eps);
1312   //
1313   int nbOfCells=getNumberOfCells();
1314   const int *conn=_nodal_connec->getConstPointer();
1315   const int *index=_nodal_connec_index->getConstPointer();
1316   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1317   connINew->alloc(nbOfCells+1,1);
1318   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1320   bool changed=false;
1321   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1322     {
1323       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1324         {
1325           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1326           changed=true;
1327         }
1328       else
1329         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1330       *connINewPtr=connNew->getNumberOfTuples();
1331     }
1332   if(changed)
1333     setConnectivity(connNew,connINew,false);
1334 }
1335
1336 /*!
1337  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1338  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1339  * the format of returned DataArrayInt instance.
1340  * 
1341  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1342  * \sa MEDCouplingUMesh::getNodeIdsInUse
1343  */
1344 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1345 {
1346   checkConnectivityFullyDefined();
1347   int nbOfCells=getNumberOfCells();
1348   const int *connIndex=_nodal_connec_index->getConstPointer();
1349   const int *conn=_nodal_connec->getConstPointer();
1350   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1351   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1352   std::vector<bool> retS(maxElt,false);
1353   for(int i=0;i<nbOfCells;i++)
1354     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1355       if(conn[j]>=0)
1356         retS[conn[j]]=true;
1357   int sz=0;
1358   for(int i=0;i<maxElt;i++)
1359     if(retS[i])
1360       sz++;
1361   DataArrayInt *ret=DataArrayInt::New();
1362   ret->alloc(sz,1);
1363   int *retPtr=ret->getPointer();
1364   for(int i=0;i<maxElt;i++)
1365     if(retS[i])
1366       *retPtr++=i;
1367   return ret;
1368 }
1369
1370 /*!
1371  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1372  * \sa MEDCouplingUMesh::getNodeIdsInUse
1373  */
1374 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1375 {
1376   int nbOfNodes=(int)nodeIdsInUse.size();
1377   int nbOfCells=getNumberOfCells();
1378   const int *connIndex=_nodal_connec_index->getConstPointer();
1379   const int *conn=_nodal_connec->getConstPointer();
1380   for(int i=0;i<nbOfCells;i++)
1381     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1382       if(conn[j]>=0)
1383         {
1384           if(conn[j]<nbOfNodes)
1385             nodeIdsInUse[conn[j]]=true;
1386           else
1387             {
1388               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1389               throw INTERP_KERNEL::Exception(oss.str().c_str());
1390             }
1391         }
1392 }
1393
1394 /*!
1395  * Finds nodes not used in any cell and returns an array giving a new id to every node
1396  * by excluding the unused nodes, for which the array holds -1. The result array is
1397  * a mapping in "Old to New" mode. 
1398  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1399  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1400  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1401  *          if the node is unused or a new id else. The caller is to delete this
1402  *          array using decrRef() as it is no more needed.  
1403  *  \throw If the coordinates array is not set.
1404  *  \throw If the nodal connectivity of cells is not defined.
1405  *  \throw If the nodal connectivity includes an invalid id.
1406  *
1407  *  \if ENABLE_EXAMPLES
1408  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1409  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1410  *  \endif
1411  * \sa computeNodeIdsAlg()
1412  */
1413 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1414 {
1415   nbrOfNodesInUse=-1;
1416   int nbOfNodes=getNumberOfNodes();
1417   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1418   ret->alloc(nbOfNodes,1);
1419   int *traducer=ret->getPointer();
1420   std::fill(traducer,traducer+nbOfNodes,-1);
1421   int nbOfCells=getNumberOfCells();
1422   const int *connIndex=_nodal_connec_index->getConstPointer();
1423   const int *conn=_nodal_connec->getConstPointer();
1424   for(int i=0;i<nbOfCells;i++)
1425     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1426       if(conn[j]>=0)
1427         {
1428           if(conn[j]<nbOfNodes)
1429             traducer[conn[j]]=1;
1430           else
1431             {
1432               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1433               throw INTERP_KERNEL::Exception(oss.str().c_str());
1434             }
1435         }
1436   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1437   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1438   return ret.retn();
1439 }
1440
1441 /*!
1442  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1443  * For each cell in \b this the number of nodes constituting cell is computed.
1444  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1445  * So for pohyhedrons some nodes can be counted several times in the returned result.
1446  * 
1447  * \return a newly allocated array
1448  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1449  */
1450 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1451 {
1452   checkConnectivityFullyDefined();
1453   int nbOfCells=getNumberOfCells();
1454   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1455   ret->alloc(nbOfCells,1);
1456   int *retPtr=ret->getPointer();
1457   const int *conn=getNodalConnectivity()->getConstPointer();
1458   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1459   for(int i=0;i<nbOfCells;i++,retPtr++)
1460     {
1461       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1462         *retPtr=connI[i+1]-connI[i]-1;
1463       else
1464         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1465     }
1466   return ret.retn();
1467 }
1468
1469 /*!
1470  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1471  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1472  *
1473  * \return DataArrayInt * - new object to be deallocated by the caller.
1474  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1475  */
1476 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1477 {
1478   checkConnectivityFullyDefined();
1479   int nbOfCells=getNumberOfCells();
1480   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1481   ret->alloc(nbOfCells,1);
1482   int *retPtr=ret->getPointer();
1483   const int *conn=getNodalConnectivity()->getConstPointer();
1484   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1485   for(int i=0;i<nbOfCells;i++,retPtr++)
1486     {
1487       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1488       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1489         *retPtr=(int)s.size();
1490       else
1491         {
1492           s.erase(-1);
1493           *retPtr=(int)s.size();
1494         }
1495     }
1496   return ret.retn();
1497 }
1498
1499 /*!
1500  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1501  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1502  * 
1503  * \return a newly allocated array
1504  */
1505 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1506 {
1507   checkConnectivityFullyDefined();
1508   int nbOfCells=getNumberOfCells();
1509   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1510   ret->alloc(nbOfCells,1);
1511   int *retPtr=ret->getPointer();
1512   const int *conn=getNodalConnectivity()->getConstPointer();
1513   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1514   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1515     {
1516       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1517       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1518     }
1519   return ret.retn();
1520 }
1521
1522 /*!
1523  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1524  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1525  * array mean that the corresponding old node is no more used. 
1526  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1527  *           this->getNumberOfNodes() before call of this method. The caller is to
1528  *           delete this array using decrRef() as it is no more needed. 
1529  *  \throw If the coordinates array is not set.
1530  *  \throw If the nodal connectivity of cells is not defined.
1531  *  \throw If the nodal connectivity includes an invalid id.
1532  *
1533  *  \if ENABLE_EXAMPLES
1534  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1535  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1536  *  \endif
1537  */
1538 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1539 {
1540   return MEDCouplingPointSet::zipCoordsTraducer();
1541 }
1542
1543 /*!
1544  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1545  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1546  */
1547 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1548 {
1549   switch(compType)
1550     {
1551     case 0:
1552       return AreCellsEqual0(conn,connI,cell1,cell2);
1553     case 1:
1554       return AreCellsEqual1(conn,connI,cell1,cell2);
1555     case 2:
1556       return AreCellsEqual2(conn,connI,cell1,cell2);
1557     case 3:
1558       return AreCellsEqual3(conn,connI,cell1,cell2);
1559     case 7:
1560       return AreCellsEqual7(conn,connI,cell1,cell2);
1561     }
1562   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1563 }
1564
1565 /*!
1566  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1567  */
1568 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1569 {
1570   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1571     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1572   return 0;
1573 }
1574
1575 /*!
1576  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1577  */
1578 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1579 {
1580   int sz=connI[cell1+1]-connI[cell1];
1581   if(sz==connI[cell2+1]-connI[cell2])
1582     {
1583       if(conn[connI[cell1]]==conn[connI[cell2]])
1584         {
1585           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1586           unsigned dim=cm.getDimension();
1587           if(dim!=3)
1588             {
1589               if(dim!=1)
1590                 {
1591                   int sz1=2*(sz-1);
1592                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1593                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1594                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1595                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1596                   return work!=tmp+sz1?1:0;
1597                 }
1598               else
1599                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1600             }
1601           else
1602             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1603         }
1604     }
1605   return 0;
1606 }
1607
1608 /*!
1609  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1610  */
1611 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1612 {
1613   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1614     {
1615       if(conn[connI[cell1]]==conn[connI[cell2]])
1616         {
1617           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1618           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1619           return s1==s2?1:0;
1620         }
1621     }
1622   return 0;
1623 }
1624
1625 /*!
1626  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1627  */
1628 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1629 {
1630   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1631     {
1632       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1633       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1634       return s1==s2?1:0;
1635     }
1636   return 0;
1637 }
1638
1639 /*!
1640  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1641  */
1642 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1643 {
1644   int sz=connI[cell1+1]-connI[cell1];
1645   if(sz==connI[cell2+1]-connI[cell2])
1646     {
1647       if(conn[connI[cell1]]==conn[connI[cell2]])
1648         {
1649           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1650           unsigned dim=cm.getDimension();
1651           if(dim!=3)
1652             {
1653               if(dim!=1)
1654                 {
1655                   int sz1=2*(sz-1);
1656                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1657                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1658                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1659                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1660                   if(work!=tmp+sz1)
1661                     return 1;
1662                   else
1663                     {
1664                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1665                       std::reverse_iterator<int *> it2((int *)tmp);
1666                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1667                         return 2;
1668                       else
1669                         return 0;
1670                     }
1671                   
1672                   return work!=tmp+sz1?1:0;
1673                 }
1674               else
1675                 {//case of SEG2 and SEG3
1676                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1677                     return 1;
1678                   if(!cm.isQuadratic())
1679                     {
1680                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1681                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1682                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1683                         return 2;
1684                       return 0;
1685                     }
1686                   else
1687                     {
1688                       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])
1689                         return 2;
1690                       return 0;
1691                     }
1692                 }
1693             }
1694           else
1695             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1696         }
1697     }
1698   return 0;
1699 }
1700
1701 /*!
1702  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1703  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1704  * and result remains unchanged.
1705  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1706  * If in 'candidates' pool -1 value is considered as an empty value.
1707  * WARNING this method returns only ONE set of result !
1708  */
1709 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1710 {
1711   if(candidates.size()<1)
1712     return false;
1713   bool ret=false;
1714   std::vector<int>::const_iterator iter=candidates.begin();
1715   int start=(*iter++);
1716   for(;iter!=candidates.end();iter++)
1717     {
1718       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1719       if(status!=0)
1720         {
1721           if(!ret)
1722             {
1723               result->pushBackSilent(start);
1724               ret=true;
1725             }
1726           if(status==1)
1727             result->pushBackSilent(*iter);
1728           else
1729             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1730         }
1731     }
1732   return ret;
1733 }
1734
1735 /*!
1736  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1737  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1738  *
1739  * \param [in] compType input specifying the technique used to compare cells each other.
1740  *   - 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.
1741  *   - 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)
1742  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1743  *   - 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
1744  * can be used for users not sensitive to orientation of cell
1745  * \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.
1746  * \param [out] commonCells
1747  * \param [out] commonCellsI
1748  * \return the correspondance array old to new in a newly allocated array.
1749  * 
1750  */
1751 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1752 {
1753   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1754   getReverseNodalConnectivity(revNodal,revNodalI);
1755   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1756 }
1757
1758 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1759                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1760 {
1761   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1762   int nbOfCells=nodalI->getNumberOfTuples()-1;
1763   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1764   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1765   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1766   std::vector<bool> isFetched(nbOfCells,false);
1767   if(startCellId==0)
1768     {
1769       for(int i=0;i<nbOfCells;i++)
1770         {
1771           if(!isFetched[i])
1772             {
1773               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1774               std::vector<int> v,v2;
1775               if(connOfNode!=connPtr+connIPtr[i+1])
1776                 {
1777                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1778                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1779                   connOfNode++;
1780                 }
1781               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1782                 if(*connOfNode>=0)
1783                   {
1784                     v=v2;
1785                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1786                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1787                     v2.resize(std::distance(v2.begin(),it));
1788                   }
1789               if(v2.size()>1)
1790                 {
1791                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1792                     {
1793                       int pos=commonCellsI->back();
1794                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1795                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1796                         isFetched[*it]=true;
1797                     }
1798                 }
1799             }
1800         }
1801     }
1802   else
1803     {
1804       for(int i=startCellId;i<nbOfCells;i++)
1805         {
1806           if(!isFetched[i])
1807             {
1808               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1809               std::vector<int> v,v2;
1810               if(connOfNode!=connPtr+connIPtr[i+1])
1811                 {
1812                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1813                   connOfNode++;
1814                 }
1815               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1816                 if(*connOfNode>=0)
1817                   {
1818                     v=v2;
1819                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1820                     v2.resize(std::distance(v2.begin(),it));
1821                   }
1822               if(v2.size()>1)
1823                 {
1824                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1825                     {
1826                       int pos=commonCellsI->back();
1827                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1828                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1829                         isFetched[*it]=true;
1830                     }
1831                 }
1832             }
1833         }
1834     }
1835   commonCellsArr=commonCells.retn();
1836   commonCellsIArr=commonCellsI.retn();
1837 }
1838
1839 /*!
1840  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1841  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1842  * than \a other->getNumberOfCells() in the returned array means that there is no
1843  * corresponding cell in \a this mesh.
1844  * It is expected that \a this and \a other meshes share the same node coordinates
1845  * array, if it is not so an exception is thrown. 
1846  *  \param [in] other - the mesh to compare with.
1847  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1848  *         valid values [0,1,2], see zipConnectivityTraducer().
1849  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1850  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1851  *         values. The caller is to delete this array using
1852  *         decrRef() as it is no more needed.
1853  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1854  *         mesh.
1855  *
1856  *  \if ENABLE_EXAMPLES
1857  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1858  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1859  *  \endif
1860  *  \sa checkDeepEquivalOnSameNodesWith()
1861  *  \sa checkGeoEquivalWith()
1862  */
1863 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1864 {
1865   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1866   int nbOfCells=getNumberOfCells();
1867   static const int possibleCompType[]={0,1,2};
1868   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1869     {
1870       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1871       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1872       oss << " !";
1873       throw INTERP_KERNEL::Exception(oss.str().c_str());
1874     }
1875   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1876   arr=o2n->substr(nbOfCells);
1877   arr->setName(other->getName());
1878   int tmp;
1879   if(other->getNumberOfCells()==0)
1880     return true;
1881   return arr->getMaxValue(tmp)<nbOfCells;
1882 }
1883
1884 /*!
1885  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1886  * This method tries to determine if \b other is fully included in \b this.
1887  * The main difference is that this method is not expected to throw exception.
1888  * This method has two outputs :
1889  *
1890  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1891  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1892  */
1893 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1894 {
1895   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1896   DataArrayInt *commonCells=0,*commonCellsI=0;
1897   int thisNbCells=getNumberOfCells();
1898   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1899   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1900   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1901   int otherNbCells=other->getNumberOfCells();
1902   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1903   arr2->alloc(otherNbCells,1);
1904   arr2->fillWithZero();
1905   int *arr2Ptr=arr2->getPointer();
1906   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1907   for(int i=0;i<nbOfCommon;i++)
1908     {
1909       int start=commonCellsPtr[commonCellsIPtr[i]];
1910       if(start<thisNbCells)
1911         {
1912           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1913             {
1914               int sig=commonCellsPtr[j]>0?1:-1;
1915               int val=std::abs(commonCellsPtr[j])-1;
1916               if(val>=thisNbCells)
1917                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1918             }
1919         }
1920     }
1921   arr2->setName(other->getName());
1922   if(arr2->presenceOfValue(0))
1923     return false;
1924   arr=arr2.retn();
1925   return true;
1926 }
1927
1928 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1929 {
1930   if(!other)
1931     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1932   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1933   if(!otherC)
1934     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1935   std::vector<const MEDCouplingUMesh *> ms(2);
1936   ms[0]=this;
1937   ms[1]=otherC;
1938   return MergeUMeshesOnSameCoords(ms);
1939 }
1940
1941 /*!
1942  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1943  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1944  * cellIds is not given explicitely but by a range python like.
1945  * 
1946  * \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.
1947  * \return a newly allocated
1948  * 
1949  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1950  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1951  */
1952 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
1953 {
1954   if(getMeshDimension()!=-1)
1955     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1956   else
1957     {
1958       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1959       if(newNbOfCells!=1)
1960         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1961       if(start!=0)
1962         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1963       incrRef();
1964       return const_cast<MEDCouplingUMesh *>(this);
1965     }
1966 }
1967
1968 /*!
1969  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1970  * The result mesh shares or not the node coordinates array with \a this mesh depending
1971  * on \a keepCoords parameter.
1972  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1973  *           to write this mesh to the MED file, its cells must be sorted using
1974  *           sortCellsInMEDFileFrmt().
1975  *  \param [in] begin - an array of cell ids to include to the new mesh.
1976  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1977  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1978  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1979  *         by calling zipCoords().
1980  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1981  *         to delete this mesh using decrRef() as it is no more needed. 
1982  *  \throw If the coordinates array is not set.
1983  *  \throw If the nodal connectivity of cells is not defined.
1984  *  \throw If any cell id in the array \a begin is not valid.
1985  *
1986  *  \if ENABLE_EXAMPLES
1987  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1988  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1989  *  \endif
1990  */
1991 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1992 {
1993   if(getMeshDimension()!=-1)
1994     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1995   else
1996     {
1997       if(end-begin!=1)
1998         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1999       if(begin[0]!=0)
2000         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2001       incrRef();
2002       return const_cast<MEDCouplingUMesh *>(this);
2003     }
2004 }
2005
2006 /*!
2007  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2008  *
2009  * 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.
2010  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2011  * The number of cells of \b this will remain the same with this method.
2012  *
2013  * \param [in] begin begin of cell ids (included) of cells in this to assign
2014  * \param [in] end end of cell ids (excluded) of cells in this to assign
2015  * \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 ).
2016  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2017  */
2018 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2019 {
2020   checkConnectivityFullyDefined();
2021   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2022   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2023     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2024   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2025     {
2026       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2027       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2028       throw INTERP_KERNEL::Exception(oss.str().c_str());
2029     }
2030   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2031   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2032     {
2033       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2034       throw INTERP_KERNEL::Exception(oss.str().c_str());
2035     }
2036   int nbOfCells=getNumberOfCells();
2037   bool easyAssign=true;
2038   const int *connI=_nodal_connec_index->getConstPointer();
2039   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2040   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2041     {
2042       if(*it>=0 && *it<nbOfCells)
2043         {
2044           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2045         }
2046       else
2047         {
2048           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2049           throw INTERP_KERNEL::Exception(oss.str().c_str());
2050         }
2051     }
2052   if(easyAssign)
2053     {
2054       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2055       computeTypes();
2056     }
2057   else
2058     {
2059       DataArrayInt *arrOut=0,*arrIOut=0;
2060       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2061                                                arrOut,arrIOut);
2062       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2063       setConnectivity(arrOut,arrIOut,true);
2064     }
2065 }
2066
2067 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2068 {
2069   checkConnectivityFullyDefined();
2070   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2071   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2072     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2073   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2074     {
2075       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2076       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2077       throw INTERP_KERNEL::Exception(oss.str().c_str());
2078     }
2079   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2080   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2081     {
2082       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2083       throw INTERP_KERNEL::Exception(oss.str().c_str());
2084     }
2085   int nbOfCells=getNumberOfCells();
2086   bool easyAssign=true;
2087   const int *connI=_nodal_connec_index->getConstPointer();
2088   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2089   int it=start;
2090   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2091     {
2092       if(it>=0 && it<nbOfCells)
2093         {
2094           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2095         }
2096       else
2097         {
2098           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2099           throw INTERP_KERNEL::Exception(oss.str().c_str());
2100         }
2101     }
2102   if(easyAssign)
2103     {
2104       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2105       computeTypes();
2106     }
2107   else
2108     {
2109       DataArrayInt *arrOut=0,*arrIOut=0;
2110       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2111                                                 arrOut,arrIOut);
2112       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2113       setConnectivity(arrOut,arrIOut,true);
2114     }
2115 }                      
2116
2117 /*!
2118  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2119  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2120  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2121  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2122  *
2123  * \param [in] begin input start of array of node ids.
2124  * \param [in] end input end of array of node ids.
2125  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2126  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2127  */
2128 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2129 {
2130   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2131   checkConnectivityFullyDefined();
2132   int tmp=-1;
2133   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2134   std::vector<bool> fastFinder(sz,false);
2135   for(const int *work=begin;work!=end;work++)
2136     if(*work>=0 && *work<sz)
2137       fastFinder[*work]=true;
2138   int nbOfCells=getNumberOfCells();
2139   const int *conn=getNodalConnectivity()->getConstPointer();
2140   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2141   for(int i=0;i<nbOfCells;i++)
2142     {
2143       int ref=0,nbOfHit=0;
2144       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2145         if(*work2>=0)
2146           {
2147             ref++;
2148             if(fastFinder[*work2])
2149               nbOfHit++;
2150           }
2151       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2152         cellIdsKept->pushBackSilent(i);
2153     }
2154   cellIdsKeptArr=cellIdsKept.retn();
2155 }
2156
2157 /*!
2158  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2159  * this->getMeshDimension(), that bound some cells of \a this mesh.
2160  * The cells of lower dimension to include to the result mesh are selected basing on
2161  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2162  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2163  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2164  * created mesh shares the node coordinates array with \a this mesh. 
2165  *  \param [in] begin - the array of node ids.
2166  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2167  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2168  *         array \a begin are added, else cells whose any node is in the
2169  *         array \a begin are added.
2170  *  \return MEDCouplingPointSet * - 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  *  \throw If any node id in \a begin is not valid.
2175  *
2176  *  \if ENABLE_EXAMPLES
2177  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2178  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2179  *  \endif
2180  */
2181 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2182 {
2183   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2184   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2185   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2186   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2187   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2188 }
2189
2190 /*!
2191  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2192  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2193  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2194  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2195  *         by calling zipCoords().
2196  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2197  *         to delete this mesh using decrRef() as it is no more needed. 
2198  *  \throw If the coordinates array is not set.
2199  *  \throw If the nodal connectivity of cells is not defined.
2200  *
2201  *  \if ENABLE_EXAMPLES
2202  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2203  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2204  *  \endif
2205  */
2206 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2207 {
2208   DataArrayInt *desc=DataArrayInt::New();
2209   DataArrayInt *descIndx=DataArrayInt::New();
2210   DataArrayInt *revDesc=DataArrayInt::New();
2211   DataArrayInt *revDescIndx=DataArrayInt::New();
2212   //
2213   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2214   revDesc->decrRef();
2215   desc->decrRef();
2216   descIndx->decrRef();
2217   int nbOfCells=meshDM1->getNumberOfCells();
2218   const int *revDescIndxC=revDescIndx->getConstPointer();
2219   std::vector<int> boundaryCells;
2220   for(int i=0;i<nbOfCells;i++)
2221     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2222       boundaryCells.push_back(i);
2223   revDescIndx->decrRef();
2224   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2225   return ret;
2226 }
2227
2228 /*!
2229  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2230  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2231  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2232  */
2233 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2234 {
2235   checkFullyDefined();
2236   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2238   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2239   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2240   //
2241   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2242   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2243   //
2244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2245   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2246   const int *revDescPtr=revDesc->getConstPointer();
2247   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2248   int nbOfCells=getNumberOfCells();
2249   std::vector<bool> ret1(nbOfCells,false);
2250   int sz=0;
2251   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2252     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2253       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2254   //
2255   DataArrayInt *ret2=DataArrayInt::New();
2256   ret2->alloc(sz,1);
2257   int *ret2Ptr=ret2->getPointer();
2258   sz=0;
2259   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2260     if(*it)
2261       *ret2Ptr++=sz;
2262   ret2->setName("BoundaryCells");
2263   return ret2;
2264 }
2265
2266 /*!
2267  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2268  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2269  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2270  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2271  *
2272  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2273  * This method method returns cells ids set s = s1 + s2 where :
2274  * 
2275  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2276  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2277  *
2278  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2279  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2280  *
2281  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2282  * \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
2283  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2284  */
2285 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2286 {
2287   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2288     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2289   checkConnectivityFullyDefined();
2290   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2291   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2292     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2293   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2294   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2295   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2296   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2297   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2298   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2299   DataArrayInt *idsOtherInConsti=0;
2300   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2301   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2302   if(!b)
2303     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2304   std::set<int> s1;
2305   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2306     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2308   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2309   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2310   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2311   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2312   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2313   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2314   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2315   neighThisPartAuto=0;
2316   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2317   const int li[2]={0,1};
2318   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2319   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2321   s_renum1->sort();
2322   //
2323   cellIdsRk0=s0arr.retn();
2324   cellIdsRk1=s_renum1.retn();
2325 }
2326
2327 /*!
2328  * 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
2329  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2330  * 
2331  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2332  */
2333 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2334 {
2335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2337   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2339   //
2340   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2341   revDesc=0; desc=0; descIndx=0;
2342   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2343   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2344   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2345 }
2346
2347 /*!
2348  * Finds nodes lying on the boundary of \a this mesh.
2349  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2350  *          nodes. The caller is to delete this array using decrRef() as it is no
2351  *          more needed.
2352  *  \throw If the coordinates array is not set.
2353  *  \throw If the nodal connectivity of cells is node defined.
2354  *
2355  *  \if ENABLE_EXAMPLES
2356  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2357  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2358  *  \endif
2359  */
2360 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2361 {
2362   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2363   return skin->computeFetchedNodeIds();
2364 }
2365
2366 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2367 {
2368   incrRef();
2369   return const_cast<MEDCouplingUMesh *>(this);
2370 }
2371
2372 /*!
2373  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2374  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2375  * 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.
2376  * 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.
2377  * 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.
2378  *
2379  * \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
2380  *             parameter is altered during the call.
2381  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2382  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2383  * \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.
2384  *
2385  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2386  */
2387 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2388                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2389 {
2390   checkFullyDefined();
2391   otherDimM1OnSameCoords.checkFullyDefined();
2392   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2393     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2394   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2395     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2396   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2397   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2398   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2400   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2401   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2402   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2403   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2405   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2406   //
2407   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2408   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2409   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2410   DataArrayInt *idsTmp=0;
2411   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2412   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2413   if(!b)
2414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2415   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2416   DataArrayInt *tmp0=0,*tmp1=0;
2417   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2418   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2419   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2420   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2421   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2422   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2423   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2424   //
2425   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2426   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2427   nodeIdsToDuplicate=s3.retn();
2428 }
2429
2430 /*!
2431  * This method operates a modification of the connectivity and coords in \b this.
2432  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2433  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2434  * 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
2435  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2436  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2437  * 
2438  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2439  * 
2440  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2441  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2442  */
2443 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2444 {
2445   int nbOfNodes=getNumberOfNodes();
2446   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2447   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2448 }
2449
2450 /*!
2451  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2452  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2453  * This method is a generalization of shiftNodeNumbersInConn().
2454  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2455  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2456  *         this->getNumberOfNodes(), in "Old to New" mode. 
2457  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2458  *  \throw If the nodal connectivity of cells is not defined.
2459  *
2460  *  \if ENABLE_EXAMPLES
2461  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2462  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2463  *  \endif
2464  */
2465 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2466 {
2467   checkConnectivityFullyDefined();
2468   int *conn=getNodalConnectivity()->getPointer();
2469   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2470   int nbOfCells=getNumberOfCells();
2471   for(int i=0;i<nbOfCells;i++)
2472     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2473       {
2474         int& node=conn[iconn];
2475         if(node>=0)//avoid polyhedron separator
2476           {
2477             node=newNodeNumbersO2N[node];
2478           }
2479       }
2480   _nodal_connec->declareAsNew();
2481   updateTime();
2482 }
2483
2484 /*!
2485  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2486  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2487  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2488  * 
2489  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2490  */
2491 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2492 {
2493   checkConnectivityFullyDefined();
2494   int *conn=getNodalConnectivity()->getPointer();
2495   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2496   int nbOfCells=getNumberOfCells();
2497   for(int i=0;i<nbOfCells;i++)
2498     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2499       {
2500         int& node=conn[iconn];
2501         if(node>=0)//avoid polyhedron separator
2502           {
2503             node+=delta;
2504           }
2505       }
2506   _nodal_connec->declareAsNew();
2507   updateTime();
2508 }
2509
2510 /*!
2511  * This method operates a modification of the connectivity in \b this.
2512  * 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.
2513  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2514  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2515  * 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
2516  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2517  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2518  * 
2519  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2520  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2521  * 
2522  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2523  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2524  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2525  */
2526 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2527 {
2528   checkConnectivityFullyDefined();
2529   std::map<int,int> m;
2530   int val=offset;
2531   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2532     m[*work]=val;
2533   int *conn=getNodalConnectivity()->getPointer();
2534   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2535   int nbOfCells=getNumberOfCells();
2536   for(int i=0;i<nbOfCells;i++)
2537     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2538       {
2539         int& node=conn[iconn];
2540         if(node>=0)//avoid polyhedron separator
2541           {
2542             std::map<int,int>::iterator it=m.find(node);
2543             if(it!=m.end())
2544               node=(*it).second;
2545           }
2546       }
2547   updateTime();
2548 }
2549
2550 /*!
2551  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2552  *
2553  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2554  * After the call of this method the number of cells remains the same as before.
2555  *
2556  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2557  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2558  * be strictly in [0;this->getNumberOfCells()).
2559  *
2560  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2561  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2562  * should be contained in[0;this->getNumberOfCells()).
2563  * 
2564  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2565  */
2566 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2567 {
2568   checkConnectivityFullyDefined();
2569   int nbCells=getNumberOfCells();
2570   const int *array=old2NewBg;
2571   if(check)
2572     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2573   //
2574   const int *conn=_nodal_connec->getConstPointer();
2575   const int *connI=_nodal_connec_index->getConstPointer();
2576   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2577   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2578   const int *n2oPtr=n2o->begin();
2579   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2580   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2581   newConn->copyStringInfoFrom(*_nodal_connec);
2582   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2583   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2584   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2585   //
2586   int *newC=newConn->getPointer();
2587   int *newCI=newConnI->getPointer();
2588   int loc=0;
2589   newCI[0]=loc;
2590   for(int i=0;i<nbCells;i++)
2591     {
2592       int pos=n2oPtr[i];
2593       int nbOfElts=connI[pos+1]-connI[pos];
2594       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2595       loc+=nbOfElts;
2596       newCI[i+1]=loc;
2597     }
2598   //
2599   setConnectivity(newConn,newConnI);
2600   if(check)
2601     free(const_cast<int *>(array));
2602 }
2603
2604 /*!
2605  * Finds cells whose bounding boxes intersect a given bounding box.
2606  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2607  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2608  *         zMax (if in 3D). 
2609  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2610  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2611  *         extent of the bounding box of cell to produce an addition to this bounding box.
2612  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2613  *         cells. The caller is to delete this array using decrRef() as it is no more
2614  *         needed. 
2615  *  \throw If the coordinates array is not set.
2616  *  \throw If the nodal connectivity of cells is not defined.
2617  *
2618  *  \if ENABLE_EXAMPLES
2619  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2620  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2621  *  \endif
2622  */
2623 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2624 {
2625   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2626   if(getMeshDimension()==-1)
2627     {
2628       elems->pushBackSilent(0);
2629       return elems.retn();
2630     }
2631   int dim=getSpaceDimension();
2632   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2633   const int* conn      = getNodalConnectivity()->getConstPointer();
2634   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2635   const double* coords = getCoords()->getConstPointer();
2636   int nbOfCells=getNumberOfCells();
2637   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2638     {
2639       for (int i=0; i<dim; i++)
2640         {
2641           elem_bb[i*2]=std::numeric_limits<double>::max();
2642           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2643         }
2644
2645       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2646         {
2647           int node= conn[inode];
2648           if(node>=0)//avoid polyhedron separator
2649             {
2650               for (int idim=0; idim<dim; idim++)
2651                 {
2652                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2653                     {
2654                       elem_bb[idim*2] = coords[node*dim+idim] ;
2655                     }
2656                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2657                     {
2658                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2659                     }
2660                 }
2661             }
2662         }
2663       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2664         elems->pushBackSilent(ielem);
2665     }
2666   return elems.retn();
2667 }
2668
2669 /*!
2670  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2671  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2672  * added in 'elems' parameter.
2673  */
2674 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2675 {
2676   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2677   if(getMeshDimension()==-1)
2678     {
2679       elems->pushBackSilent(0);
2680       return elems.retn();
2681     }
2682   int dim=getSpaceDimension();
2683   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2684   const int* conn      = getNodalConnectivity()->getConstPointer();
2685   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2686   const double* coords = getCoords()->getConstPointer();
2687   int nbOfCells=getNumberOfCells();
2688   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2689     {
2690       for (int i=0; i<dim; i++)
2691         {
2692           elem_bb[i*2]=std::numeric_limits<double>::max();
2693           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2694         }
2695
2696       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2697         {
2698           int node= conn[inode];
2699           if(node>=0)//avoid polyhedron separator
2700             {
2701               for (int idim=0; idim<dim; idim++)
2702                 {
2703                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2704                     {
2705                       elem_bb[idim*2] = coords[node*dim+idim] ;
2706                     }
2707                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2708                     {
2709                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2710                     }
2711                 }
2712             }
2713         }
2714       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2715         elems->pushBackSilent(ielem);
2716     }
2717   return elems.retn();
2718 }
2719
2720 /*!
2721  * Returns a type of a cell by its id.
2722  *  \param [in] cellId - the id of the cell of interest.
2723  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2724  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2725  */
2726 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2727 {
2728   const int *ptI=_nodal_connec_index->getConstPointer();
2729   const int *pt=_nodal_connec->getConstPointer();
2730   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2731     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2732   else
2733     {
2734       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2735       throw INTERP_KERNEL::Exception(oss.str().c_str());
2736     }
2737 }
2738
2739 /*!
2740  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2741  * This method does not throw exception if geometric type \a type is not in \a this.
2742  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2743  * The coordinates array is not considered here.
2744  *
2745  * \param [in] type the geometric type
2746  * \return cell ids in this having geometric type \a type.
2747  */
2748 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2749 {
2750   
2751   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2752   ret->alloc(0,1);
2753   checkConnectivityFullyDefined();
2754   int nbCells=getNumberOfCells();
2755   int mdim=getMeshDimension();
2756   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2757   if(mdim!=(int)cm.getDimension())
2758     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2759   const int *ptI=_nodal_connec_index->getConstPointer();
2760   const int *pt=_nodal_connec->getConstPointer();
2761   for(int i=0;i<nbCells;i++)
2762     {
2763       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2764         ret->pushBackSilent(i);
2765     }
2766   return ret.retn();
2767 }
2768
2769 /*!
2770  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2771  */
2772 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2773 {
2774   const int *ptI=_nodal_connec_index->getConstPointer();
2775   const int *pt=_nodal_connec->getConstPointer();
2776   int nbOfCells=getNumberOfCells();
2777   int ret=0;
2778   for(int i=0;i<nbOfCells;i++)
2779     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2780       ret++;
2781   return ret;
2782 }
2783
2784 /*!
2785  * Returns the nodal connectivity of a given cell.
2786  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2787  * all returned node ids can be used in getCoordinatesOfNode().
2788  *  \param [in] cellId - an id of the cell of interest.
2789  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2790  *         cleared before the appending.
2791  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2792  */
2793 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2794 {
2795   const int *ptI=_nodal_connec_index->getConstPointer();
2796   const int *pt=_nodal_connec->getConstPointer();
2797   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2798     if(*w>=0)
2799       conn.push_back(*w);
2800 }
2801
2802 std::string MEDCouplingUMesh::simpleRepr() const
2803 {
2804   static const char msg0[]="No coordinates specified !";
2805   std::ostringstream ret;
2806   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2807   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2808   int tmpp1,tmpp2;
2809   double tt=getTime(tmpp1,tmpp2);
2810   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2811   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2812   if(_mesh_dim>=-1)
2813     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2814   else
2815     { ret << " Mesh dimension has not been set or is invalid !"; }
2816   if(_coords!=0)
2817     {
2818       const int spaceDim=getSpaceDimension();
2819       ret << spaceDim << "\nInfo attached on space dimension : ";
2820       for(int i=0;i<spaceDim;i++)
2821         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2822       ret << "\n";
2823     }
2824   else
2825     ret << msg0 << "\n";
2826   ret << "Number of nodes : ";
2827   if(_coords!=0)
2828     ret << getNumberOfNodes() << "\n";
2829   else
2830     ret << msg0 << "\n";
2831   ret << "Number of cells : ";
2832   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2833     ret << getNumberOfCells() << "\n";
2834   else
2835     ret << "No connectivity specified !" << "\n";
2836   ret << "Cell types present : ";
2837   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2838     {
2839       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2840       ret << cm.getRepr() << " ";
2841     }
2842   ret << "\n";
2843   return ret.str();
2844 }
2845
2846 std::string MEDCouplingUMesh::advancedRepr() const
2847 {
2848   std::ostringstream ret;
2849   ret << simpleRepr();
2850   ret << "\nCoordinates array : \n___________________\n\n";
2851   if(_coords)
2852     _coords->reprWithoutNameStream(ret);
2853   else
2854     ret << "No array set !\n";
2855   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2856   reprConnectivityOfThisLL(ret);
2857   return ret.str();
2858 }
2859
2860 /*!
2861  * This method returns a C++ code that is a dump of \a this.
2862  * This method will throw if this is not fully defined.
2863  */
2864 std::string MEDCouplingUMesh::cppRepr() const
2865 {
2866   static const char coordsName[]="coords";
2867   static const char connName[]="conn";
2868   static const char connIName[]="connI";
2869   checkFullyDefined();
2870   std::ostringstream ret; ret << "// coordinates" << std::endl;
2871   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2872   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2873   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2874   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2875   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2876   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2877   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2878   return ret.str();
2879 }
2880
2881 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2882 {
2883   std::ostringstream ret;
2884   reprConnectivityOfThisLL(ret);
2885   return ret.str();
2886 }
2887
2888 /*!
2889  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2890  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2891  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2892  * some algos).
2893  * 
2894  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2895  * 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
2896  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2897  */
2898 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2899 {
2900   int mdim=getMeshDimension();
2901   if(mdim<0)
2902     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2903   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2904   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2905   bool needToCpyCT=true;
2906   if(!_nodal_connec)
2907     {
2908       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2909       needToCpyCT=false;
2910     }
2911   else
2912     {
2913       tmp1=_nodal_connec;
2914       tmp1->incrRef();
2915     }
2916   if(!_nodal_connec_index)
2917     {
2918       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2919       needToCpyCT=false;
2920     }
2921   else
2922     {
2923       tmp2=_nodal_connec_index;
2924       tmp2->incrRef();
2925     }
2926   ret->setConnectivity(tmp1,tmp2,false);
2927   if(needToCpyCT)
2928     ret->_types=_types;
2929   if(!_coords)
2930     {
2931       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2932       ret->setCoords(coords);
2933     }
2934   else
2935     ret->setCoords(_coords);
2936   return ret.retn();
2937 }
2938
2939 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2940 {
2941   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2942     {
2943       int nbOfCells=getNumberOfCells();
2944       const int *c=_nodal_connec->getConstPointer();
2945       const int *ci=_nodal_connec_index->getConstPointer();
2946       for(int i=0;i<nbOfCells;i++)
2947         {
2948           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2949           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2950           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2951           stream << "\n";
2952         }
2953     }
2954   else
2955     stream << "Connectivity not defined !\n";
2956 }
2957
2958 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2959 {
2960   const int *ptI=_nodal_connec_index->getConstPointer();
2961   const int *pt=_nodal_connec->getConstPointer();
2962   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2963     return ptI[cellId+1]-ptI[cellId]-1;
2964   else
2965     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2966 }
2967
2968 /*!
2969  * Returns types of cells of the specified part of \a this mesh.
2970  * This method avoids computing sub-mesh explicitely to get its types.
2971  *  \param [in] begin - an array of cell ids of interest.
2972  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2973  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2974  *         describing the cell types. 
2975  *  \throw If the coordinates array is not set.
2976  *  \throw If the nodal connectivity of cells is not defined.
2977  *  \sa getAllGeoTypes()
2978  */
2979 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
2980 {
2981   checkFullyDefined();
2982   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2983   const int *conn=_nodal_connec->getConstPointer();
2984   const int *connIndex=_nodal_connec_index->getConstPointer();
2985   for(const int *w=begin;w!=end;w++)
2986     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2987   return ret;
2988 }
2989
2990 /*!
2991  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2992  * a set of types of cells constituting \a this mesh. 
2993  * This method is for advanced users having prepared their connectivity before. For
2994  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2995  *  \param [in] conn - the nodal connectivity array. 
2996  *  \param [in] connIndex - the nodal connectivity index array.
2997  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2998  *         mesh is updated.
2999  */
3000 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3001 {
3002   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3003   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3004   if(isComputingTypes)
3005     computeTypes();
3006   declareAsNew();
3007 }
3008
3009 /*!
3010  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3011  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3012  */
3013 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3014                                                                                  _nodal_connec(0),_nodal_connec_index(0),
3015                                                                                 _types(other._types)
3016 {
3017   if(other._nodal_connec)
3018     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3019   if(other._nodal_connec_index)
3020     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3021 }
3022
3023 MEDCouplingUMesh::~MEDCouplingUMesh()
3024 {
3025   if(_nodal_connec)
3026     _nodal_connec->decrRef();
3027   if(_nodal_connec_index)
3028     _nodal_connec_index->decrRef();
3029 }
3030
3031 /*!
3032  * Recomputes a set of cell types of \a this mesh. For more info see
3033  * \ref MEDCouplingUMeshNodalConnectivity.
3034  */
3035 void MEDCouplingUMesh::computeTypes()
3036 {
3037   if(_nodal_connec && _nodal_connec_index)
3038     {
3039       _types.clear();
3040       const int *conn=_nodal_connec->getConstPointer();
3041       const int *connIndex=_nodal_connec_index->getConstPointer();
3042       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3043       if (nbOfElem > 0)
3044         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3045           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3046     }
3047 }
3048
3049 /*!
3050  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3051  */
3052 void MEDCouplingUMesh::checkFullyDefined() const
3053 {
3054   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3055     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3056 }
3057
3058 /*!
3059  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3060  */
3061 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3062 {
3063   if(!_nodal_connec_index || !_nodal_connec)
3064     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3065 }
3066
3067 /*!
3068  * Returns a number of cells constituting \a this mesh. 
3069  *  \return int - the number of cells in \a this mesh.
3070  *  \throw If the nodal connectivity of cells is not defined.
3071  */
3072 int MEDCouplingUMesh::getNumberOfCells() const
3073
3074   if(_nodal_connec_index)
3075     return _nodal_connec_index->getNumberOfTuples()-1;
3076   else
3077     if(_mesh_dim==-1)
3078       return 1;
3079     else
3080       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3081 }
3082
3083 /*!
3084  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3085  * mesh. For more info see \ref MEDCouplingMeshesPage.
3086  *  \return int - the dimension of \a this mesh.
3087  *  \throw If the mesh dimension is not defined using setMeshDimension().
3088  */
3089 int MEDCouplingUMesh::getMeshDimension() const
3090 {
3091   if(_mesh_dim<-1)
3092     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3093   return _mesh_dim;
3094 }
3095
3096 /*!
3097  * Returns a length of the nodal connectivity array.
3098  * This method is for test reason. Normally the integer returned is not useable by
3099  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3100  *  \return int - the length of the nodal connectivity array.
3101  */
3102 int MEDCouplingUMesh::getMeshLength() const
3103 {
3104   return _nodal_connec->getNbOfElems();
3105 }
3106
3107 /*!
3108  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3109  */
3110 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3111 {
3112   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3113   tinyInfo.push_back(getMeshDimension());
3114   tinyInfo.push_back(getNumberOfCells());
3115   if(_nodal_connec)
3116     tinyInfo.push_back(getMeshLength());
3117   else
3118     tinyInfo.push_back(-1);
3119 }
3120
3121 /*!
3122  * First step of unserialization process.
3123  */
3124 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3125 {
3126   return tinyInfo[6]<=0;
3127 }
3128
3129 /*!
3130  * Second step of serialization process.
3131  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3132  */
3133 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3134 {
3135   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3136   if(tinyInfo[5]!=-1)
3137     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3138 }
3139
3140 /*!
3141  * Third and final step of serialization process.
3142  */
3143 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3144 {
3145   MEDCouplingPointSet::serialize(a1,a2);
3146   if(getMeshDimension()>-1)
3147     {
3148       a1=DataArrayInt::New();
3149       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3150       int *ptA1=a1->getPointer();
3151       const int *conn=getNodalConnectivity()->getConstPointer();
3152       const int *index=getNodalConnectivityIndex()->getConstPointer();
3153       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3154       std::copy(conn,conn+getMeshLength(),ptA1);
3155     }
3156   else
3157     a1=0;
3158 }
3159
3160 /*!
3161  * Second and final unserialization process.
3162  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3163  */
3164 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3165 {
3166   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3167   setMeshDimension(tinyInfo[5]);
3168   if(tinyInfo[7]!=-1)
3169     {
3170       // Connectivity
3171       const int *recvBuffer=a1->getConstPointer();
3172       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3173       myConnecIndex->alloc(tinyInfo[6]+1,1);
3174       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3175       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3176       myConnec->alloc(tinyInfo[7],1);
3177       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3178       setConnectivity(myConnec, myConnecIndex);
3179     }
3180 }
3181
3182 /*!
3183  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3184  * CellIds are given using range specified by a start an end and step.
3185  */
3186 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3187 {
3188   checkFullyDefined();
3189   int ncell=getNumberOfCells();
3190   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3191   ret->_mesh_dim=_mesh_dim;
3192   ret->setCoords(_coords);
3193   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3194   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3195   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3196   int work=start;
3197   const int *conn=_nodal_connec->getConstPointer();
3198   const int *connIndex=_nodal_connec_index->getConstPointer();
3199   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3200     {
3201       if(work>=0 && work<ncell)
3202         {
3203           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3204         }
3205       else
3206         {
3207           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3208           throw INTERP_KERNEL::Exception(oss.str().c_str());
3209         }
3210     }
3211   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3212   int *newConnPtr=newConn->getPointer();
3213   std::set<INTERP_KERNEL::NormalizedCellType> types;
3214   work=start;
3215   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3216     {
3217       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3218       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3219     }
3220   ret->setConnectivity(newConn,newConnI,false);
3221   ret->_types=types;
3222   ret->copyTinyInfoFrom(this);
3223   return ret.retn();
3224 }
3225
3226 /*!
3227  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3228  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3229  * The return newly allocated mesh will share the same coordinates as \a this.
3230  */
3231 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3232 {
3233   checkConnectivityFullyDefined();
3234   int ncell=getNumberOfCells();
3235   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3236   ret->_mesh_dim=_mesh_dim;
3237   ret->setCoords(_coords);
3238   std::size_t nbOfElemsRet=std::distance(begin,end);
3239   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3240   connIndexRet[0]=0;
3241   const int *conn=_nodal_connec->getConstPointer();
3242   const int *connIndex=_nodal_connec_index->getConstPointer();
3243   int newNbring=0;
3244   for(const int *work=begin;work!=end;work++,newNbring++)
3245     {
3246       if(*work>=0 && *work<ncell)
3247         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3248       else
3249         {
3250           free(connIndexRet);
3251           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3252           throw INTERP_KERNEL::Exception(oss.str().c_str());
3253         }
3254     }
3255   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3256   int *connRetWork=connRet;
3257   std::set<INTERP_KERNEL::NormalizedCellType> types;
3258   for(const int *work=begin;work!=end;work++)
3259     {
3260       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3261       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3262     }
3263   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3264   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3265   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3266   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3267   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3268   ret->_types=types;
3269   ret->copyTinyInfoFrom(this);
3270   return ret.retn();
3271 }
3272
3273 /*!
3274  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3275  * mesh.<br>
3276  * For 1D cells, the returned field contains lengths.<br>
3277  * For 2D cells, the returned field contains areas.<br>
3278  * For 3D cells, the returned field contains volumes.
3279  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3280  *         orientation, i.e. the volume is always positive.
3281  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3282  *         and one time . The caller is to delete this field using decrRef() as it is no
3283  *         more needed.
3284  */
3285 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3286 {
3287   std::string name="MeasureOfMesh_";
3288   name+=getName();
3289   int nbelem=getNumberOfCells();
3290   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3291   field->setName(name);
3292   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3293   array->alloc(nbelem,1);
3294   double *area_vol=array->getPointer();
3295   field->setArray(array) ; array=0;
3296   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3297   field->synchronizeTimeWithMesh();
3298   if(getMeshDimension()!=-1)
3299     {
3300       int ipt;
3301       INTERP_KERNEL::NormalizedCellType type;
3302       int dim_space=getSpaceDimension();
3303       const double *coords=getCoords()->getConstPointer();
3304       const int *connec=getNodalConnectivity()->getConstPointer();
3305       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3306       for(int iel=0;iel<nbelem;iel++)
3307         {
3308           ipt=connec_index[iel];
3309           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3310           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);
3311         }
3312       if(isAbs)
3313         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3314     }
3315   else
3316     {
3317       area_vol[0]=std::numeric_limits<double>::max();
3318     }
3319   return field.retn();
3320 }
3321
3322 /*!
3323  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3324  * mesh.<br>
3325  * For 1D cells, the returned array contains lengths.<br>
3326  * For 2D cells, the returned array contains areas.<br>
3327  * For 3D cells, the returned array contains volumes.
3328  * This method avoids building explicitly a part of \a this mesh to perform the work.
3329  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3330  *         orientation, i.e. the volume is always positive.
3331  *  \param [in] begin - an array of cell ids of interest.
3332  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3333  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3334  *          delete this array using decrRef() as it is no more needed.
3335  * 
3336  *  \if ENABLE_EXAMPLES
3337  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3338  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3339  *  \endif
3340  *  \sa getMeasureField()
3341  */
3342 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3343 {
3344   std::string name="PartMeasureOfMesh_";
3345   name+=getName();
3346   int nbelem=(int)std::distance(begin,end);
3347   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3348   array->setName(name);
3349   array->alloc(nbelem,1);
3350   double *area_vol=array->getPointer();
3351   if(getMeshDimension()!=-1)
3352     {
3353       int ipt;
3354       INTERP_KERNEL::NormalizedCellType type;
3355       int dim_space=getSpaceDimension();
3356       const double *coords=getCoords()->getConstPointer();
3357       const int *connec=getNodalConnectivity()->getConstPointer();
3358       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3359       for(const int *iel=begin;iel!=end;iel++)
3360         {
3361           ipt=connec_index[*iel];
3362           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3363           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3364         }
3365       if(isAbs)
3366         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3367     }
3368   else
3369     {
3370       area_vol[0]=std::numeric_limits<double>::max();
3371     }
3372   return array.retn();
3373 }
3374
3375 /*!
3376  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3377  * \a this one. The returned field contains the dual cell volume for each corresponding
3378  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3379  *  the dual mesh in P1 sens of \a this.<br>
3380  * For 1D cells, the returned field contains lengths.<br>
3381  * For 2D cells, the returned field contains areas.<br>
3382  * For 3D cells, the returned field contains volumes.
3383  * This method is useful to check "P1*" conservative interpolators.
3384  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3385  *         orientation, i.e. the volume is always positive.
3386  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3387  *          nodes and one time. The caller is to delete this array using decrRef() as
3388  *          it is no more needed.
3389  */
3390 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3391 {
3392   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3393   std::string name="MeasureOnNodeOfMesh_";
3394   name+=getName();
3395   int nbNodes=getNumberOfNodes();
3396   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3397   double cst=1./((double)getMeshDimension()+1.);
3398   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3399   array->alloc(nbNodes,1);
3400   double *valsToFill=array->getPointer();
3401   std::fill(valsToFill,valsToFill+nbNodes,0.);
3402   const double *values=tmp->getArray()->getConstPointer();
3403   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3405   getReverseNodalConnectivity(da,daInd);
3406   const int *daPtr=da->getConstPointer();
3407   const int *daIPtr=daInd->getConstPointer();
3408   for(int i=0;i<nbNodes;i++)
3409     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3410       valsToFill[i]+=cst*values[*cell];
3411   ret->setMesh(this);
3412   ret->setArray(array);
3413   return ret.retn();
3414 }
3415
3416 /*!
3417  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3418  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3419  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3420  * and are normalized.
3421  * <br> \a this can be either 
3422  * - a  2D mesh in 2D or 3D space or 
3423  * - an 1D mesh in 2D space.
3424  * 
3425  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3426  *          cells and one time. The caller is to delete this field using decrRef() as
3427  *          it is no more needed.
3428  *  \throw If the nodal connectivity of cells is not defined.
3429  *  \throw If the coordinates array is not set.
3430  *  \throw If the mesh dimension is not set.
3431  *  \throw If the mesh and space dimension is not as specified above.
3432  */
3433 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3434 {
3435   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3436     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3437   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3438   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3439   int nbOfCells=getNumberOfCells();
3440   int nbComp=getMeshDimension()+1;
3441   array->alloc(nbOfCells,nbComp);
3442   double *vals=array->getPointer();
3443   const int *connI=_nodal_connec_index->getConstPointer();
3444   const int *conn=_nodal_connec->getConstPointer();
3445   const double *coords=_coords->getConstPointer();
3446   if(getMeshDimension()==2)
3447     {
3448       if(getSpaceDimension()==3)
3449         {
3450           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3451           const double *locPtr=loc->getConstPointer();
3452           for(int i=0;i<nbOfCells;i++,vals+=3)
3453             {
3454               int offset=connI[i];
3455               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3456               double n=INTERP_KERNEL::norm<3>(vals);
3457               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3458             }
3459         }
3460       else
3461         {
3462           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3463           const double *isAbsPtr=isAbs->getArray()->begin();
3464           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3465             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3466         }
3467     }
3468   else//meshdimension==1
3469     {
3470       double tmp[2];
3471       for(int i=0;i<nbOfCells;i++)
3472         {
3473           int offset=connI[i];
3474           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3475           double n=INTERP_KERNEL::norm<2>(tmp);
3476           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3477           *vals++=-tmp[1];
3478           *vals++=tmp[0];
3479         }
3480     }
3481   ret->setArray(array);
3482   ret->setMesh(this);
3483   ret->synchronizeTimeWithSupport();
3484   return ret.retn();
3485 }
3486
3487 /*!
3488  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3489  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3490  * and are normalized.
3491  * <br> \a this can be either 
3492  * - a  2D mesh in 2D or 3D space or 
3493  * - an 1D mesh in 2D space.
3494  * 
3495  * This method avoids building explicitly a part of \a this mesh to perform the work.
3496  *  \param [in] begin - an array of cell ids of interest.
3497  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3498  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3499  *          cells and one time. The caller is to delete this field using decrRef() as
3500  *          it is no more needed.
3501  *  \throw If the nodal connectivity of cells is not defined.
3502  *  \throw If the coordinates array is not set.
3503  *  \throw If the mesh dimension is not set.
3504  *  \throw If the mesh and space dimension is not as specified above.
3505  *  \sa buildOrthogonalField()
3506  *
3507  *  \if ENABLE_EXAMPLES
3508  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3509  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3510  *  \endif
3511  */
3512 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3513 {
3514   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3515     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3516   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3517   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3518   std::size_t nbelems=std::distance(begin,end);
3519   int nbComp=getMeshDimension()+1;
3520   array->alloc((int)nbelems,nbComp);
3521   double *vals=array->getPointer();
3522   const int *connI=_nodal_connec_index->getConstPointer();
3523   const int *conn=_nodal_connec->getConstPointer();
3524   const double *coords=_coords->getConstPointer();
3525   if(getMeshDimension()==2)
3526     {
3527       if(getSpaceDimension()==3)
3528         {
3529           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3530           const double *locPtr=loc->getConstPointer();
3531           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3532             {
3533               int offset=connI[*i];
3534               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3535               double n=INTERP_KERNEL::norm<3>(vals);
3536               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3537             }
3538         }
3539       else
3540         {
3541           for(std::size_t i=0;i<nbelems;i++)
3542             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3543         }
3544     }
3545   else//meshdimension==1
3546     {
3547       double tmp[2];
3548       for(const int *i=begin;i!=end;i++)
3549         {
3550           int offset=connI[*i];
3551           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3552           double n=INTERP_KERNEL::norm<2>(tmp);
3553           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3554           *vals++=-tmp[1];
3555           *vals++=tmp[0];
3556         }
3557     }
3558   ret->setArray(array);
3559   ret->setMesh(this);
3560   ret->synchronizeTimeWithSupport();
3561   return ret.retn();
3562 }
3563
3564 /*!
3565  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3566  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3567  * and are \b not normalized.
3568  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3569  *          cells and one time. The caller is to delete this field using decrRef() as
3570  *          it is no more needed.
3571  *  \throw If the nodal connectivity of cells is not defined.
3572  *  \throw If the coordinates array is not set.
3573  *  \throw If \a this->getMeshDimension() != 1.
3574  *  \throw If \a this mesh includes cells of type other than SEG2.
3575  */
3576 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3577 {
3578    if(getMeshDimension()!=1)
3579     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3580    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3581      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3582    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3583    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3584    int nbOfCells=getNumberOfCells();
3585    int spaceDim=getSpaceDimension();
3586    array->alloc(nbOfCells,spaceDim);
3587    double *pt=array->getPointer();
3588    const double *coo=getCoords()->getConstPointer();
3589    std::vector<int> conn;
3590    conn.reserve(2);
3591    for(int i=0;i<nbOfCells;i++)
3592      {
3593        conn.resize(0);
3594        getNodeIdsOfCell(i,conn);
3595        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3596      }
3597    ret->setArray(array);
3598    ret->setMesh(this);
3599    ret->synchronizeTimeWithSupport();
3600    return ret.retn();   
3601 }
3602
3603 /*!
3604  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3605  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3606  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3607  * from. If a result face is shared by two 3D cells, then the face in included twice in
3608  * the result mesh.
3609  *  \param [in] origin - 3 components of a point defining location of the plane.
3610  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3611  *         must be greater than 1e-6.
3612  *  \param [in] eps - half-thickness of the plane.
3613  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3614  *         producing correspondent 2D cells. The caller is to delete this array
3615  *         using decrRef() as it is no more needed.
3616  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3617  *         not share the node coordinates array with \a this mesh. The caller is to
3618  *         delete this mesh using decrRef() as it is no more needed.  
3619  *  \throw If the coordinates array is not set.
3620  *  \throw If the nodal connectivity of cells is not defined.
3621  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3622  *  \throw If magnitude of \a vec is less than 1e-6.
3623  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3624  *  \throw If \a this includes quadratic cells.
3625  */
3626 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3627 {
3628   checkFullyDefined();
3629   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3630     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3631   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3632   if(candidates->empty())
3633     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3634   std::vector<int> nodes;
3635   DataArrayInt *cellIds1D=0;
3636   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3637   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3638   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3639   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3640   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3641   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3642   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3643   revDesc2=0; revDescIndx2=0;
3644   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3645   revDesc1=0; revDescIndx1=0;
3646   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3647   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3648   //
3649   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3650   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3651     cut3DCurve[*it]=-1;
3652   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3653   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3654   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3655                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3656                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3657   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3658   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3659   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3660   if(cellIds2->empty())
3661     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3662   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3663   ret->setCoords(mDesc1->getCoords());
3664   ret->setConnectivity(conn,connI,true);
3665   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3666   return ret.retn();
3667 }
3668
3669 /*!
3670  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3671 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
3672 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3673 the result mesh.
3674  *  \param [in] origin - 3 components of a point defining location of the plane.
3675  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3676  *         must be greater than 1e-6.
3677  *  \param [in] eps - half-thickness of the plane.
3678  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3679  *         producing correspondent segments. The caller is to delete this array
3680  *         using decrRef() as it is no more needed.
3681  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3682  *         mesh in 3D space. This mesh does not share the node coordinates array with
3683  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3684  *         no more needed. 
3685  *  \throw If the coordinates array is not set.
3686  *  \throw If the nodal connectivity of cells is not defined.
3687  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3688  *  \throw If magnitude of \a vec is less than 1e-6.
3689  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3690  *  \throw If \a this includes quadratic cells.
3691  */
3692 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3693 {
3694   checkFullyDefined();
3695   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3696     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3697   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3698   if(candidates->empty())
3699     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3700   std::vector<int> nodes;
3701   DataArrayInt *cellIds1D=0;
3702   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3703   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3704   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3705   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3706   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3707   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3708   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3709   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3710   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3711   //
3712   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3713   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3714     cut3DCurve[*it]=-1;
3715   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3716   int ncellsSub=subMesh->getNumberOfCells();
3717   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3718   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3719                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3720                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3721   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3722   conn->alloc(0,1);
3723   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3724   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3725   for(int i=0;i<ncellsSub;i++)
3726     {
3727       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3728         {
3729           if(cut3DSurf[i].first!=-2)
3730             {
3731               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3732               connI->pushBackSilent(conn->getNumberOfTuples());
3733               cellIds2->pushBackSilent(i);
3734             }
3735           else
3736             {
3737               int cellId3DSurf=cut3DSurf[i].second;
3738               int offset=nodalI[cellId3DSurf]+1;
3739               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3740               for(int j=0;j<nbOfEdges;j++)
3741                 {
3742                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3743                   connI->pushBackSilent(conn->getNumberOfTuples());
3744                   cellIds2->pushBackSilent(cellId3DSurf);
3745                 }
3746             }
3747         }
3748     }
3749   if(cellIds2->empty())
3750     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3751   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3752   ret->setCoords(mDesc1->getCoords());
3753   ret->setConnectivity(conn,connI,true);
3754   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3755   return ret.retn();
3756 }
3757
3758 /*!
3759  * Finds cells whose bounding boxes intersect a given plane.
3760  *  \param [in] origin - 3 components of a point defining location of the plane.
3761  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3762  *         must be greater than 1e-6.
3763  *  \param [in] eps - half-thickness of the plane.
3764  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3765  *         cells. The caller is to delete this array using decrRef() as it is no more
3766  *         needed.
3767  *  \throw If the coordinates array is not set.
3768  *  \throw If the nodal connectivity of cells is not defined.
3769  *  \throw If \a this->getSpaceDimension() != 3.
3770  *  \throw If magnitude of \a vec is less than 1e-6.
3771  *  \sa buildSlice3D()
3772  */
3773 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3774 {
3775   checkFullyDefined();
3776   if(getSpaceDimension()!=3)
3777     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3778   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3779   if(normm<1e-6)
3780     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3781   double vec2[3];
3782   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3783   double angle=acos(vec[2]/normm);
3784   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3785   double bbox[6];
3786   if(angle>eps)
3787     {
3788       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3789       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3790       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3791       mw->setCoords(coo);
3792       mw->getBoundingBox(bbox);
3793       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3794       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3795     }
3796   else
3797     {
3798       getBoundingBox(bbox);
3799       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3800       cellIds=getCellsInBoundingBox(bbox,eps);
3801     }
3802   return cellIds.retn();
3803 }
3804
3805 /*!
3806  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3807  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3808  * No consideration of coordinate is done by this method.
3809  * 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)
3810  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3811  */
3812 bool MEDCouplingUMesh::isContiguous1D() const
3813 {
3814   if(getMeshDimension()!=1)
3815     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3816   int nbCells=getNumberOfCells();
3817   if(nbCells<1)
3818     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3819   const int *connI=_nodal_connec_index->getConstPointer();
3820   const int *conn=_nodal_connec->getConstPointer();
3821   int ref=conn[connI[0]+2];
3822   for(int i=1;i<nbCells;i++)
3823     {
3824       if(conn[connI[i]+1]!=ref)
3825         return false;
3826       ref=conn[connI[i]+2];
3827     }
3828   return true;
3829 }
3830
3831 /*!
3832  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3833  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3834  * \param pt reference point of the line
3835  * \param v normalized director vector of the line
3836  * \param eps max precision before throwing an exception
3837  * \param res output of size this->getNumberOfCells
3838  */
3839 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3840 {
3841   if(getMeshDimension()!=1)
3842     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3843    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3844      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3845    if(getSpaceDimension()!=3)
3846      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3847    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3848    const double *fPtr=f->getArray()->getConstPointer();
3849    double tmp[3];
3850    for(int i=0;i<getNumberOfCells();i++)
3851      {
3852        const double *tmp1=fPtr+3*i;
3853        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3854        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3855        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3856        double n1=INTERP_KERNEL::norm<3>(tmp);
3857        n1/=INTERP_KERNEL::norm<3>(tmp1);
3858        if(n1>eps)
3859          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3860      }
3861    const double *coo=getCoords()->getConstPointer();
3862    for(int i=0;i<getNumberOfNodes();i++)
3863      {
3864        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3865        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3866        res[i]=std::accumulate(tmp,tmp+3,0.);
3867      }
3868 }
3869
3870 /*!
3871  * 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. 
3872  * \a this is expected to be a mesh so that its space dimension is equal to its
3873  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3874  * 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).
3875  
3876  * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3877  * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3878  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3879  *
3880  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3881  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3882  *
3883  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3884  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3885  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3886  * \return the positive value of the distance.
3887  * \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
3888  * dimension - 1.
3889  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3890  */
3891 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3892 {
3893   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3894   if(meshDim!=spaceDim-1)
3895     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3896   if(meshDim!=2 && meshDim!=1)
3897     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3898   checkFullyDefined();
3899   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3900     { 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()); }
3901   DataArrayInt *ret1=0;
3902   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3903   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3904   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3905   cellId=*ret1Safe->begin();
3906   return *ret0->begin();
3907 }
3908
3909 /*!
3910  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3911  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3912  * 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
3913  * 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).
3914  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3915  * 
3916  * \a this is expected to be a mesh so that its space dimension is equal to its
3917  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3918  * 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).
3919  *
3920  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3921  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3922  *
3923  * \param [in] pts the list of points in which each tuple represents a point
3924  * \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.
3925  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3926  * \throw if number of components of \a pts is not equal to the space dimension.
3927  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3928  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3929  */
3930 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3931 {
3932   if(!pts)
3933     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3934   pts->checkAllocated();
3935   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3936   if(meshDim!=spaceDim-1)
3937     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3938   if(meshDim!=2 && meshDim!=1)
3939     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3940   if(pts->getNumberOfComponents()!=spaceDim)
3941     {
3942       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3943       throw INTERP_KERNEL::Exception(oss.str().c_str());
3944     }
3945   checkFullyDefined();
3946   int nbCells=getNumberOfCells();
3947   if(nbCells==0)
3948     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3949   int nbOfPts=pts->getNumberOfTuples();
3950   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3951   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3952   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3953   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3954   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3955   const double *bbox(bboxArr->begin());
3956   switch(spaceDim)
3957     {
3958     case 3:
3959       {
3960         BBTreeDst<3> myTree(bbox,0,0,nbCells);
3961         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3962           {
3963             double x=std::numeric_limits<double>::max();
3964             std::vector<int> elems;
3965             myTree.getMinDistanceOfMax(ptsPtr,x);
3966             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3967             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3968           }
3969         break;
3970       }
3971     case 2:
3972       {
3973         BBTreeDst<2> myTree(bbox,0,0,nbCells);
3974         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3975           {
3976             double x=std::numeric_limits<double>::max();
3977             std::vector<int> elems;
3978             myTree.getMinDistanceOfMax(ptsPtr,x);
3979             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3980             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3981           }
3982         break;
3983       }
3984     default:
3985       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3986     }
3987   cellIds=ret1.retn();
3988   return ret0.retn();
3989 }
3990
3991 /*!
3992  * \param [in] pt the start pointer (included) of the coordinates of the point
3993  * \param [in] cellIdsBg the start pointer (included) of cellIds
3994  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3995  * \param [in] nc nodal connectivity
3996  * \param [in] ncI nodal connectivity index
3997  * \param [in,out] ret0 the min distance between \a this and the external input point
3998  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3999  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4000  */
4001 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)
4002 {
4003   cellId=-1;
4004   ret0=std::numeric_limits<double>::max();
4005   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4006     {
4007       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4008         {
4009         case INTERP_KERNEL::NORM_TRI3:
4010           {
4011             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4012             if(tmp<ret0)
4013               { ret0=tmp; cellId=*zeCell; }
4014             break;
4015           }
4016         case INTERP_KERNEL::NORM_QUAD4:
4017         case INTERP_KERNEL::NORM_POLYGON:
4018           {
4019             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4020             if(tmp<ret0)
4021               { ret0=tmp; cellId=*zeCell; }
4022             break;
4023           }
4024         default:
4025           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4026         }
4027     }
4028 }
4029
4030 /*!
4031  * \param [in] pt the start pointer (included) of the coordinates of the point
4032  * \param [in] cellIdsBg the start pointer (included) of cellIds
4033  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4034  * \param [in] nc nodal connectivity
4035  * \param [in] ncI nodal connectivity index
4036  * \param [in,out] ret0 the min distance between \a this and the external input point
4037  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4038  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4039  */
4040 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)
4041 {
4042   cellId=-1;
4043   ret0=std::numeric_limits<double>::max();
4044   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4045     {
4046        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4047         {
4048         case INTERP_KERNEL::NORM_SEG2:
4049           {
4050             std::size_t uselessEntry=0;
4051             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4052             tmp=sqrt(tmp);
4053             if(tmp<ret0)
4054               { ret0=tmp; cellId=*zeCell; }
4055             break;
4056           }
4057         default:
4058           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4059         }
4060     }
4061 }
4062
4063 /*!
4064  * Finds cells in contact with a ball (i.e. a point with precision). 
4065  * 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.
4066  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4067  *
4068  * \warning This method is suitable if the caller intends to evaluate only one
4069  *          point, for more points getCellsContainingPoints() is recommended as it is
4070  *          faster. 
4071  *  \param [in] pos - array of coordinates of the ball central point.
4072  *  \param [in] eps - ball radius.
4073  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4074  *         if there are no such cells.
4075  *  \throw If the coordinates array is not set.
4076  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4077  */
4078 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4079 {
4080   std::vector<int> elts;
4081   getCellsContainingPoint(pos,eps,elts);
4082   if(elts.empty())
4083     return -1;
4084   return elts.front();
4085 }
4086
4087 /*!
4088  * Finds cells in contact with a ball (i.e. a point with precision).
4089  * 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.
4090  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4091  * \warning This method is suitable if the caller intends to evaluate only one
4092  *          point, for more points getCellsContainingPoints() is recommended as it is
4093  *          faster. 
4094  *  \param [in] pos - array of coordinates of the ball central point.
4095  *  \param [in] eps - ball radius.
4096  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4097  *         before inserting ids.
4098  *  \throw If the coordinates array is not set.
4099  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4100  *
4101  *  \if ENABLE_EXAMPLES
4102  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4103  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4104  *  \endif
4105  */
4106 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4107 {
4108   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4109   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4110   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4111 }
4112
4113 /// @cond INTERNAL
4114
4115 namespace ParaMEDMEM
4116 {
4117   template<const int SPACEDIMM>
4118   class DummyClsMCUG
4119   {
4120   public:
4121     static const int MY_SPACEDIM=SPACEDIMM;
4122     static const int MY_MESHDIM=8;
4123     typedef int MyConnType;
4124     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4125     // begin
4126     // useless, but for windows compilation ...
4127     const double* getCoordinatesPtr() const { return 0; }
4128     const int* getConnectivityPtr() const { return 0; }
4129     const int* getConnectivityIndexPtr() const { return 0; }
4130     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4131     // end
4132   };
4133   
4134   /*!
4135    * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4136    */
4137   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map<INTERP_KERNEL::Node *,int>& m)
4138   {
4139     INTERP_KERNEL::Edge *ret=0;
4140     INTERP_KERNEL::Node *n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),*n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1]));
4141     m[n0]=bg[0]; m[n1]=bg[1];
4142     switch(typ)
4143       {
4144       case INTERP_KERNEL::NORM_SEG2:
4145         {
4146           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4147           break;
4148         }
4149       case INTERP_KERNEL::NORM_SEG3:
4150         {
4151           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4152           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4153           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4154           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4155           bool colinearity(inters.areColinears());
4156           delete e1; delete e2;
4157           if(colinearity)
4158             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4159           else
4160             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4161           break;
4162         }
4163       default:
4164         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4165       } 
4166     return ret;
4167   }
4168
4169   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4170   {
4171     INTERP_KERNEL::Edge *ret=0;
4172     switch(typ)
4173       {
4174       case INTERP_KERNEL::NORM_SEG2:
4175         {
4176           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4177           break;
4178         }
4179       case INTERP_KERNEL::NORM_SEG3:
4180         {
4181           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4182           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4183           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4184           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4185           bool colinearity=inters.areColinears();
4186           delete e1; delete e2;
4187           if(colinearity)
4188             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4189           else
4190             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4191           mapp2[bg[2]].second=false;
4192           break;
4193         }
4194       default:
4195         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4196       }
4197     return ret;
4198   }
4199
4200   /*!
4201    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4202    * the global mesh 'mDesc'.
4203    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4204    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4205    */
4206   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4207       std::map<INTERP_KERNEL::Node *,int>& mapp)
4208       throw(INTERP_KERNEL::Exception)
4209   {
4210     mapp.clear();
4211     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.
4212     const double *coo=mDesc->getCoords()->getConstPointer();
4213     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4214     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4215     std::set<int> s;
4216     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4217       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4218     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4219       {
4220         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4221         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4222       }
4223     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4224     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4225       {
4226         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4227         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4228       }
4229     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4230       {
4231         if((*it2).second.second)
4232           mapp[(*it2).second.first]=(*it2).first;
4233         ((*it2).second.first)->decrRef();
4234       }
4235     return ret;
4236   }
4237
4238   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4239   {
4240     if(nodeId>=offset2)
4241       {
4242         int locId=nodeId-offset2;
4243         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4244       }
4245     if(nodeId>=offset1)
4246       {
4247         int locId=nodeId-offset1;
4248         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4249       }
4250     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4251   }
4252
4253   /**
4254    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4255    */
4256   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4257                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4258                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4259   {
4260     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4261       {
4262         int eltId1=abs(*desc1)-1;
4263         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4264           {
4265             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4266             if(it==mappRev.end())
4267               {
4268                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4269                 mapp[node]=*it1;
4270                 mappRev[*it1]=node;
4271               }
4272           }
4273       }
4274   }
4275 }
4276
4277 /// @endcond
4278
4279 template<int SPACEDIM>
4280 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4281                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4282 {
4283   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4284   int *eltsIndexPtr(eltsIndex->getPointer());
4285   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4286   const double *bbox(bboxArr->begin());
4287   int nbOfCells=getNumberOfCells();
4288   const int *conn=_nodal_connec->getConstPointer();
4289   const int *connI=_nodal_connec_index->getConstPointer();
4290   double bb[2*SPACEDIM];
4291   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4292   for(int i=0;i<nbOfPoints;i++)
4293     {
4294       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4295       for(int j=0;j<SPACEDIM;j++)
4296         {
4297           bb[2*j]=pos[SPACEDIM*i+j];
4298           bb[2*j+1]=pos[SPACEDIM*i+j];
4299         }
4300       std::vector<int> candidates;
4301       myTree.getIntersectingElems(bb,candidates);
4302       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4303         {
4304           int sz(connI[(*iter)+1]-connI[*iter]-1);
4305           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4306           bool status(false);
4307           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4308             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4309           else
4310             {
4311               if(SPACEDIM!=2)
4312                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4313               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4314               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4315               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4316               INTERP_KERNEL::QuadraticPolygon *pol(0);
4317               for(int j=0;j<sz;j++)
4318                 {
4319                   int nodeId(conn[connI[*iter]+1+j]);
4320                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4321                 }
4322               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4323                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4324               else
4325                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4326               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4327               double a(0.),b(0.),c(0.);
4328               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4329               status=pol->isInOrOut2(n);
4330               delete pol; n->decrRef();
4331             }
4332           if(status)
4333             {
4334               eltsIndexPtr[i+1]++;
4335               elts->pushBackSilent(*iter);
4336             }
4337         }
4338     }
4339 }
4340 /*!
4341  * Finds cells in contact with several balls (i.e. points with precision).
4342  * This method is an extension of getCellContainingPoint() and
4343  * getCellsContainingPoint() for the case of multiple points.
4344  * 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.
4345  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4346  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4347  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4348  *         this->getSpaceDimension() * \a nbOfPoints 
4349  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4350  *  \param [in] eps - radius of balls (i.e. the precision).
4351  *  \param [out] elts - vector returning ids of found cells.
4352  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4353  *         dividing cell ids in \a elts into groups each referring to one
4354  *         point. Its every element (except the last one) is an index pointing to the
4355  *         first id of a group of cells. For example cells in contact with the *i*-th
4356  *         point are described by following range of indices:
4357  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4358  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4359  *         Number of cells in contact with the *i*-th point is
4360  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4361  *  \throw If the coordinates array is not set.
4362  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4363  *
4364  *  \if ENABLE_EXAMPLES
4365  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4366  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4367  *  \endif
4368  */
4369 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4370                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4371 {
4372   int spaceDim=getSpaceDimension();
4373   int mDim=getMeshDimension();
4374   if(spaceDim==3)
4375     {
4376       if(mDim==3)
4377         {
4378           const double *coords=_coords->getConstPointer();
4379           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4380         }
4381       /*else if(mDim==2)
4382         {
4383           
4384         }*/
4385       else
4386         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4387     }
4388   else if(spaceDim==2)
4389     {
4390       if(mDim==2)
4391         {
4392           const double *coords=_coords->getConstPointer();
4393           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4394         }
4395       else
4396         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4397     }
4398   else if(spaceDim==1)
4399     {
4400       if(mDim==1)
4401         {
4402           const double *coords=_coords->getConstPointer();
4403           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4404         }
4405       else
4406         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4407     }
4408   else
4409     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4410 }
4411
4412 /*!
4413  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4414  * least two its edges intersect each other anywhere except their extremities. An
4415  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4416  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4417  *         cleared before filling in.
4418  *  \param [in] eps - precision.
4419  *  \throw If \a this->getMeshDimension() != 2.
4420  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4421  */
4422 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4423 {
4424   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4425   if(getMeshDimension()!=2)
4426     throw INTERP_KERNEL::Exception(msg);
4427   int spaceDim=getSpaceDimension();
4428   if(spaceDim!=2 && spaceDim!=3)
4429     throw INTERP_KERNEL::Exception(msg);
4430   const int *conn=_nodal_connec->getConstPointer();
4431   const int *connI=_nodal_connec_index->getConstPointer();
4432   int nbOfCells=getNumberOfCells();
4433   std::vector<double> cell2DinS2;
4434   for(int i=0;i<nbOfCells;i++)
4435     {
4436       int offset=connI[i];
4437       int nbOfNodesForCell=connI[i+1]-offset-1;
4438       if(nbOfNodesForCell<=3)
4439         continue;
4440       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4441       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4442       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4443         cells.push_back(i);
4444       cell2DinS2.clear();
4445     }
4446 }
4447
4448 /*!
4449  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4450  *
4451  * 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.
4452  * 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.
4453  * 
4454  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4455  * This convex envelop is computed using Jarvis march algorithm.
4456  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4457  * 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)
4458  * 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.
4459  *
4460  * \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.
4461  * \sa MEDCouplingUMesh::colinearize2D
4462  */
4463 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4464 {
4465   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4466     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4467   checkFullyDefined();
4468   const double *coords=getCoords()->getConstPointer();
4469   int nbOfCells=getNumberOfCells();
4470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4471   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4472   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4473   int *workIndexOut=nodalConnecIndexOut->getPointer();
4474   *workIndexOut=0;
4475   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4476   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4477   std::set<INTERP_KERNEL::NormalizedCellType> types;
4478   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4479   isChanged->alloc(0,1);
4480   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4481     {
4482       int pos=nodalConnecOut->getNumberOfTuples();
4483       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4484         isChanged->pushBackSilent(i);
4485       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4486       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4487     }
4488   if(isChanged->empty())
4489     return 0;
4490   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4491   _types=types;
4492   return isChanged.retn();
4493 }
4494
4495 /*!
4496  * This method is \b NOT const because it can modify \a this.
4497  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4498  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4499  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4500  * \b 1 for translation and rotation around point of 'mesh1D'.
4501  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4502  */
4503 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4504 {
4505   checkFullyDefined();
4506   mesh1D->checkFullyDefined();
4507   if(!mesh1D->isContiguous1D())
4508     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4509   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4510     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4511   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4512     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4513   if(mesh1D->getMeshDimension()!=1)
4514     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4515   bool isQuad=false;
4516   if(isPresenceOfQuadratic())
4517     {
4518       if(mesh1D->isFullyQuadratic())
4519         isQuad=true;
4520       else
4521         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4522     }
4523   zipCoords();
4524   int oldNbOfNodes=getNumberOfNodes();
4525   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4526   switch(policy)
4527     {
4528     case 0:
4529       {
4530         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4531         break;
4532       }
4533     case 1:
4534       {
4535         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4536         break;
4537       }
4538     default:
4539       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4540     }
4541   setCoords(newCoords);
4542   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4543   updateTime();
4544   return ret.retn();
4545 }
4546
4547 /*!
4548  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4549  * If it is not the case an exception will be thrown.
4550  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4551  * intersection of plane defined by ('origin','vec').
4552  * This method has one in/out parameter : 'cut3DCurve'.
4553  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4554  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4555  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4556  * This method will throw an exception if \a this contains a non linear segment.
4557  */
4558 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4559 {
4560   checkFullyDefined();
4561   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4562     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4563   int ncells=getNumberOfCells();
4564   int nnodes=getNumberOfNodes();
4565   double vec2[3],vec3[3],vec4[3];
4566   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4567   if(normm<1e-6)
4568     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4569   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4570   const int *conn=_nodal_connec->getConstPointer();
4571   const int *connI=_nodal_connec_index->getConstPointer();
4572   const double *coo=_coords->getConstPointer();
4573   std::vector<double> addCoo;
4574   for(int i=0;i<ncells;i++)
4575     {
4576       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4577         {
4578           if(cut3DCurve[i]==-2)
4579             {
4580               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4581               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];
4582               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4583               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4584               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4585                 {
4586                   const double *st2=coo+3*st;
4587                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4588                   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]));
4589                   if(pos>eps && pos<1-eps)
4590                     {
4591                       int nNode=((int)addCoo.size())/3;
4592                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4593                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4594                       cut3DCurve[i]=nnodes+nNode;
4595                     }
4596                 }
4597             }
4598         }
4599       else
4600         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4601     }
4602   if(!addCoo.empty())
4603     {
4604       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4605       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4606       coo2->alloc(newNbOfNodes,3);
4607       double *tmp=coo2->getPointer();
4608       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4609       std::copy(addCoo.begin(),addCoo.end(),tmp);
4610       DataArrayDouble::SetArrayIn(coo2,_coords);
4611     }
4612 }
4613
4614 /*!
4615  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4616  * \param mesh1D is the input 1D mesh used for translation computation.
4617  * \return newCoords new coords filled by this method. 
4618  */
4619 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4620 {
4621   int oldNbOfNodes=getNumberOfNodes();
4622   int nbOf1DCells=mesh1D->getNumberOfCells();
4623   int spaceDim=getSpaceDimension();
4624   DataArrayDouble *ret=DataArrayDouble::New();
4625   std::vector<bool> isQuads;
4626   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4627   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4628   double *retPtr=ret->getPointer();
4629   const double *coords=getCoords()->getConstPointer();
4630   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4631   std::vector<int> v;
4632   std::vector<double> c;
4633   double vec[3];
4634   v.reserve(3);
4635   c.reserve(6);
4636   for(int i=0;i<nbOf1DCells;i++)
4637     {
4638       v.resize(0);
4639       mesh1D->getNodeIdsOfCell(i,v);
4640       c.resize(0);
4641       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4642       mesh1D->getCoordinatesOfNode(v[0],c);
4643       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4644       for(int j=0;j<oldNbOfNodes;j++)
4645         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4646       if(isQuad)
4647         {
4648           c.resize(0);
4649           mesh1D->getCoordinatesOfNode(v[1],c);
4650           mesh1D->getCoordinatesOfNode(v[0],c);
4651           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4652           for(int j=0;j<oldNbOfNodes;j++)
4653             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4654         }
4655     }
4656   ret->copyStringInfoFrom(*getCoords());
4657   return ret;
4658 }
4659
4660 /*!
4661  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4662  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4663  * \return newCoords new coords filled by this method. 
4664  */
4665 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4666 {
4667   if(mesh1D->getSpaceDimension()==2)
4668     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4669   if(mesh1D->getSpaceDimension()==3)
4670     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4671   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4672 }
4673
4674 /*!
4675  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4676  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4677  * \return newCoords new coords filled by this method. 
4678  */
4679 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4680 {
4681   if(isQuad)
4682     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4683   int oldNbOfNodes=getNumberOfNodes();
4684   int nbOf1DCells=mesh1D->getNumberOfCells();
4685   if(nbOf1DCells<2)
4686     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4687   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4688   int nbOfLevsInVec=nbOf1DCells+1;
4689   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4690   double *retPtr=ret->getPointer();
4691   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4692   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4693   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4694   tmp->setCoords(tmp2);
4695   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4696   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4697   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4698   for(int i=1;i<nbOfLevsInVec;i++)
4699     {
4700       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4701       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4702       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4703       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4704       tmp->translate(vec);
4705       double tmp3[2],radius,alpha,alpha0;
4706       const double *p0=i+1<nbOfLevsInVec?begin:third;
4707       const double *p1=i+1<nbOfLevsInVec?end:begin;
4708       const double *p2=i+1<nbOfLevsInVec?third:end;
4709       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4710       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]);
4711       double angle=acos(cosangle/(radius*radius));
4712       tmp->rotate(end,0,angle);
4713       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4714     }
4715   return ret.retn();
4716 }
4717
4718 /*!
4719  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4720  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4721  * \return newCoords new coords filled by this method. 
4722  */
4723 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4724 {
4725   if(isQuad)
4726     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4727   int oldNbOfNodes=getNumberOfNodes();
4728   int nbOf1DCells=mesh1D->getNumberOfCells();
4729   if(nbOf1DCells<2)
4730     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4731   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4732   int nbOfLevsInVec=nbOf1DCells+1;
4733   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4734   double *retPtr=ret->getPointer();
4735   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4736   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4737   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4738   tmp->setCoords(tmp2);
4739   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4740   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4741   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4742   for(int i=1;i<nbOfLevsInVec;i++)
4743     {
4744       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4745       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4746       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4747       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4748       tmp->translate(vec);
4749       double tmp3[2],radius,alpha,alpha0;
4750       const double *p0=i+1<nbOfLevsInVec?begin:third;
4751       const double *p1=i+1<nbOfLevsInVec?end:begin;
4752       const double *p2=i+1<nbOfLevsInVec?third:end;
4753       double vecPlane[3]={
4754         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4755         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4756         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4757       };
4758       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4759       if(norm>1.e-7)
4760         {
4761           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4762           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4763           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4764           double s2=norm2;
4765           double c2=cos(asin(s2));
4766           double m[3][3]={
4767             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4768             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4769             {-vec2[1]*s2, vec2[0]*s2, c2}
4770           };
4771           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]};
4772           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]};
4773           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]};
4774           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4775           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]);
4776           double angle=acos(cosangle/(radius*radius));
4777           tmp->rotate(end,vecPlane,angle);
4778           
4779         }
4780       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4781     }
4782   return ret.retn();
4783 }
4784
4785 /*!
4786  * This method is private because not easy to use for end user. This method is const contrary to
4787  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4788  * the coords sorted slice by slice.
4789  * \param isQuad specifies presence of quadratic cells.
4790  */
4791 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4792 {
4793   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4794   int nbOf2DCells=getNumberOfCells();
4795   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4796   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4797   const int *conn=_nodal_connec->getConstPointer();
4798   const int *connI=_nodal_connec_index->getConstPointer();
4799   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4800   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4801   newConnI->alloc(nbOf3DCells+1,1);
4802   int *newConnIPtr=newConnI->getPointer();
4803   *newConnIPtr++=0;
4804   std::vector<int> newc;
4805   for(int j=0;j<nbOf2DCells;j++)
4806     {
4807       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4808       *newConnIPtr++=(int)newc.size();
4809     }
4810   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4811   int *newConnPtr=newConn->getPointer();
4812   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4813   newConnIPtr=newConnI->getPointer();
4814   for(int iz=0;iz<nbOf1DCells;iz++)
4815     {
4816       if(iz!=0)
4817         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4818       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4819         {
4820           int icell=(int)(iter-newc.begin());
4821           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4822             {
4823               if(*iter!=-1)
4824                 *newConnPtr=(*iter)+iz*deltaPerLev;
4825               else
4826                 *newConnPtr=-1;
4827             }
4828           else
4829             *newConnPtr=(*iter);
4830         }
4831     }
4832   ret->setConnectivity(newConn,newConnI,true);
4833   ret->setCoords(getCoords());
4834   return ret;
4835 }
4836
4837 /*!
4838  * Checks if \a this mesh is constituted by only quadratic cells.
4839  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4840  *  \throw If the coordinates array is not set.
4841  *  \throw If the nodal connectivity of cells is not defined.
4842  */
4843 bool MEDCouplingUMesh::isFullyQuadratic() const
4844 {
4845   checkFullyDefined();
4846   bool ret=true;
4847   int nbOfCells=getNumberOfCells();
4848   for(int i=0;i<nbOfCells && ret;i++)
4849     {
4850       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4851       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4852       ret=cm.isQuadratic();
4853     }
4854   return ret;
4855 }
4856
4857 /*!
4858  * Checks if \a this mesh includes any quadratic cell.
4859  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4860  *  \throw If the coordinates array is not set.
4861  *  \throw If the nodal connectivity of cells is not defined.
4862  */
4863 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4864 {
4865   checkFullyDefined();
4866   bool ret=false;
4867   int nbOfCells=getNumberOfCells();
4868   for(int i=0;i<nbOfCells && !ret;i++)
4869     {
4870       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4871       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4872       ret=cm.isQuadratic();
4873     }
4874   return ret;
4875 }
4876
4877 /*!
4878  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4879  * this mesh, it remains unchanged.
4880  *  \throw If the coordinates array is not set.
4881  *  \throw If the nodal connectivity of cells is not defined.
4882  */
4883 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4884 {
4885   checkFullyDefined();
4886   int nbOfCells=getNumberOfCells();
4887   int delta=0;
4888   const int *iciptr=_nodal_connec_index->getConstPointer();
4889   for(int i=0;i<nbOfCells;i++)
4890     {
4891       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4892       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4893       if(cm.isQuadratic())
4894         {
4895           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4896           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4897           if(!cml.isDynamic())
4898             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4899           else
4900             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4901         }
4902     }
4903   if(delta==0)
4904     return ;
4905   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4906   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4907   const int *icptr=_nodal_connec->getConstPointer();
4908   newConn->alloc(getMeshLength()-delta,1);
4909   newConnI->alloc(nbOfCells+1,1);
4910   int *ocptr=newConn->getPointer();
4911   int *ociptr=newConnI->getPointer();
4912   *ociptr=0;
4913   _types.clear();
4914   for(int i=0;i<nbOfCells;i++,ociptr++)
4915     {
4916       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4917       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4918       if(!cm.isQuadratic())
4919         {
4920           _types.insert(type);
4921           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4922           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4923         }
4924       else
4925         {
4926           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4927           _types.insert(typel);
4928           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4929           int newNbOfNodes=cml.getNumberOfNodes();
4930           if(cml.isDynamic())
4931             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4932           *ocptr++=(int)typel;
4933           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4934           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4935         }
4936     }
4937   setConnectivity(newConn,newConnI,false);
4938 }
4939
4940 /*!
4941  * This method converts all linear cell in \a this to quadratic one.
4942  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4943  * 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)
4944  * 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.
4945  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4946  * end of the existing coordinates.
4947  * 
4948  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4949  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4950  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4951  * 
4952  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4953  *
4954  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4955  */
4956 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4957 {
4958   DataArrayInt *conn=0,*connI=0;
4959   DataArrayDouble *coords=0;
4960   std::set<INTERP_KERNEL::NormalizedCellType> types;
4961   checkFullyDefined();
4962   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4963   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4964   int meshDim=getMeshDimension();
4965   switch(conversionType)
4966     {
4967     case 0:
4968       switch(meshDim)
4969         {
4970         case 1:
4971           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4972           connSafe=conn; connISafe=connI; coordsSafe=coords;
4973           break;
4974         case 2:
4975           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4976           connSafe=conn; connISafe=connI; coordsSafe=coords;
4977           break;
4978         case 3:
4979           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4980           connSafe=conn; connISafe=connI; coordsSafe=coords;
4981           break;
4982         default:
4983           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4984         }
4985       break;
4986     case 1:
4987       {
4988         switch(meshDim)
4989         {
4990         case 1:
4991           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4992           connSafe=conn; connISafe=connI; coordsSafe=coords;
4993           break;
4994         case 2:
4995           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4996           connSafe=conn; connISafe=connI; coordsSafe=coords;
4997           break;
4998         case 3:
4999           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5000           connSafe=conn; connISafe=connI; coordsSafe=coords;
5001           break;
5002         default:
5003           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5004         }
5005         break;
5006       }
5007     default:
5008       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5009     }
5010   setConnectivity(connSafe,connISafe,false);
5011   _types=types;
5012   setCoords(coordsSafe);
5013   return ret.retn();
5014 }
5015
5016 /*!
5017  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5018  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5019  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5020  */
5021 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5022 {
5023   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5024   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5025   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5026   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5027   int nbOfCells=getNumberOfCells();
5028   int nbOfNodes=getNumberOfNodes();
5029   const int *cPtr=_nodal_connec->getConstPointer();
5030   const int *icPtr=_nodal_connec_index->getConstPointer();
5031   int lastVal=0,offset=nbOfNodes;
5032   for(int i=0;i<nbOfCells;i++,icPtr++)
5033     {
5034       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5035       if(type==INTERP_KERNEL::NORM_SEG2)
5036         {
5037           types.insert(INTERP_KERNEL::NORM_SEG3);
5038           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5039           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5040           newConn->pushBackSilent(offset++);
5041           lastVal+=4;
5042           newConnI->pushBackSilent(lastVal);
5043           ret->pushBackSilent(i);
5044         }
5045       else
5046         {
5047           types.insert(type);
5048           lastVal+=(icPtr[1]-icPtr[0]);
5049           newConnI->pushBackSilent(lastVal);
5050           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5051         }
5052     }
5053   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5054   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5055   return ret.retn();
5056 }
5057
5058 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
5059 {
5060   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5061   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5062   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5063   //
5064   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5065   DataArrayInt *conn1D=0,*conn1DI=0;
5066   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5067   DataArrayDouble *coordsTmp=0;
5068   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5069   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5070   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5071   const int *c1DPtr=conn1D->begin();
5072   const int *c1DIPtr=conn1DI->begin();
5073   int nbOfCells=getNumberOfCells();
5074   const int *cPtr=_nodal_connec->getConstPointer();
5075   const int *icPtr=_nodal_connec_index->getConstPointer();
5076   int lastVal=0;
5077   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5078     {
5079       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5080       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5081       if(!cm.isQuadratic())
5082         {
5083           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5084           types.insert(typ2); newConn->pushBackSilent(typ2);
5085           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5086           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5087             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5088           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5089           newConnI->pushBackSilent(lastVal);
5090           ret->pushBackSilent(i);
5091         }
5092       else
5093         {
5094           types.insert(typ);
5095           lastVal+=(icPtr[1]-icPtr[0]);
5096           newConnI->pushBackSilent(lastVal);
5097           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5098         }
5099     }
5100   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5101   return ret.retn();
5102 }
5103
5104 /*!
5105  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5106  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5107  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5108  */
5109 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5110 {
5111   
5112   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5113   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5114   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5115 }
5116
5117 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5118 {
5119   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5120   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5121   //
5122   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5123   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5124   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5125   //
5126   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5127   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5128   DataArrayInt *conn1D=0,*conn1DI=0;
5129   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5130   DataArrayDouble *coordsTmp=0;
5131   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5132   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5133   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5134   const int *c1DPtr=conn1D->begin();
5135   const int *c1DIPtr=conn1DI->begin();
5136   int nbOfCells=getNumberOfCells();
5137   const int *cPtr=_nodal_connec->getConstPointer();
5138   const int *icPtr=_nodal_connec_index->getConstPointer();
5139   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5140   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5141     {
5142       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5143       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5144       if(!cm.isQuadratic())
5145         {
5146           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5147           types.insert(typ2); newConn->pushBackSilent(typ2);
5148           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5149           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5150             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5151           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5152           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5153           newConnI->pushBackSilent(lastVal);
5154           ret->pushBackSilent(i);
5155         }
5156       else
5157         {
5158           types.insert(typ);
5159           lastVal+=(icPtr[1]-icPtr[0]);
5160           newConnI->pushBackSilent(lastVal);
5161           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5162         }
5163     }
5164   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5165   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5166   return ret.retn();
5167 }
5168
5169 /*!
5170  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5171  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5172  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5173  */
5174 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5175 {
5176   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5177   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5178   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5179 }
5180
5181 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5182 {
5183   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5184   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5185   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5186   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5187   //
5188   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5189   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5190   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5191   //
5192   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5193   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5194   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5195   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5196   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5197   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5198   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5199   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5200   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5201   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5202   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5203   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5204   int nbOfCells=getNumberOfCells();
5205   const int *cPtr=_nodal_connec->getConstPointer();
5206   const int *icPtr=_nodal_connec_index->getConstPointer();
5207   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5208   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5209     {
5210       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5211       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5212       if(!cm.isQuadratic())
5213         {
5214           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5215           if(typ2==INTERP_KERNEL::NORM_ERROR)
5216             {
5217               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5218               throw INTERP_KERNEL::Exception(oss.str().c_str());
5219             }
5220           types.insert(typ2); newConn->pushBackSilent(typ2);
5221           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5222           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5223             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5224           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5225             {
5226               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5227               int tmpPos=newConn->getNumberOfTuples();
5228               newConn->pushBackSilent(nodeId2);
5229               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5230             }
5231           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5232           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5233           newConnI->pushBackSilent(lastVal);
5234           ret->pushBackSilent(i);
5235         }
5236       else
5237         {
5238           types.insert(typ);
5239           lastVal+=(icPtr[1]-icPtr[0]);
5240           newConnI->pushBackSilent(lastVal);
5241           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5242         }
5243     }
5244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5245   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5246   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5247   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5248   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5249   int *c=newConn->getPointer();
5250   const int *cI(newConnI->begin());
5251   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5252     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5253   offset=coordsTmp2Safe->getNumberOfTuples();
5254   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5255     c[cI[(*elt)+1]-1]+=offset;
5256   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5257   return ret.retn();
5258 }
5259
5260 /*!
5261  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5262  * so that the number of cells remains the same. Quadratic faces are converted to
5263  * polygons. This method works only for 2D meshes in
5264  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5265  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5266  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5267  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5268  *         a polylinized edge constituting the input polygon.
5269  *  \throw If the coordinates array is not set.
5270  *  \throw If the nodal connectivity of cells is not defined.
5271  *  \throw If \a this->getMeshDimension() != 2.
5272  *  \throw If \a this->getSpaceDimension() != 2.
5273  */
5274 void MEDCouplingUMesh::tessellate2D(double eps)
5275 {
5276   checkFullyDefined();
5277   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5278     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5279   double epsa=fabs(eps);
5280   if(epsa<std::numeric_limits<double>::min())
5281     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 !");
5282   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5283   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5284   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5285   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5286   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5287   revDesc1=0; revDescIndx1=0;
5288   mDesc->tessellate2DCurve(eps);
5289   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5290   setCoords(mDesc->getCoords());
5291 }
5292
5293 /*!
5294  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5295  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5296  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5297  *         a sub-divided edge.
5298  *  \throw If the coordinates array is not set.
5299  *  \throw If the nodal connectivity of cells is not defined.
5300  *  \throw If \a this->getMeshDimension() != 1.
5301  *  \throw If \a this->getSpaceDimension() != 2.
5302  */
5303 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5304 {
5305   checkFullyDefined();
5306   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5307     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5308   double epsa=fabs(eps);
5309   if(epsa<std::numeric_limits<double>::min())
5310     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 !");
5311   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5312   int nbCells=getNumberOfCells();
5313   int nbNodes=getNumberOfNodes();
5314   const int *conn=_nodal_connec->getConstPointer();
5315   const int *connI=_nodal_connec_index->getConstPointer();
5316   const double *coords=_coords->getConstPointer();
5317   std::vector<double> addCoo;
5318   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5320   newConnI->alloc(nbCells+1,1);
5321   int *newConnIPtr=newConnI->getPointer();
5322   *newConnIPtr=0;
5323   int tmp1[3];
5324   INTERP_KERNEL::Node *tmp2[3];
5325   std::set<INTERP_KERNEL::NormalizedCellType> types;
5326   for(int i=0;i<nbCells;i++,newConnIPtr++)
5327     {
5328       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5329       if(cm.isQuadratic())
5330         {//assert(connI[i+1]-connI[i]-1==3)
5331           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5332           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5333           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5334           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5335           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5336           if(eac)
5337             {
5338               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5339               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5340               delete eac;
5341               newConnIPtr[1]=(int)newConn.size();
5342             }
5343           else
5344             {
5345               types.insert(INTERP_KERNEL::NORM_SEG2);
5346               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5347               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5348               newConnIPtr[1]=newConnIPtr[0]+3;
5349             }
5350         }
5351       else
5352         {
5353           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5354           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5355           newConnIPtr[1]=newConnIPtr[0]+3;
5356         }
5357     }
5358   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5359     return ;
5360   _types=types;
5361   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5362   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5363   newConnArr->alloc((int)newConn.size(),1);
5364   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5365   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5366   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5367   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5368   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5369   std::copy(addCoo.begin(),addCoo.end(),work);
5370   DataArrayDouble::SetArrayIn(newCoords,_coords);
5371   updateTime();
5372 }
5373
5374 /*!
5375  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5376  * In addition, returns an array mapping new cells to old ones. <br>
5377  * This method typically increases the number of cells in \a this mesh
5378  * but the number of nodes remains \b unchanged.
5379  * That's why the 3D splitting policies
5380  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5381  *  \param [in] policy - specifies a pattern used for splitting.
5382  * The semantic of \a policy is:
5383  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5384  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5385  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5386  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5387  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5388  *          an id of old cell producing it. The caller is to delete this array using
5389  *         decrRef() as it is no more needed. 
5390  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5391  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5392  *          and \a this->getMeshDimension() != 3. 
5393  *  \throw If \a policy is not one of the four discussed above.
5394  *  \throw If the nodal connectivity of cells is not defined.
5395  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5396  */
5397 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5398 {
5399   switch(policy)
5400     {
5401     case 0:
5402       return simplexizePol0();
5403     case 1:
5404       return simplexizePol1();
5405     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5406       return simplexizePlanarFace5();
5407     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5408       return simplexizePlanarFace6();
5409     default:
5410       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)");
5411     }
5412 }
5413
5414 /*!
5415  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5416  * - 1D: INTERP_KERNEL::NORM_SEG2
5417  * - 2D: INTERP_KERNEL::NORM_TRI3
5418  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5419  *
5420  * This method is useful for users that need to use P1 field services as
5421  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5422  * All these methods need mesh support containing only simplex cells.
5423  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5424  *  \throw If the coordinates array is not set.
5425  *  \throw If the nodal connectivity of cells is not defined.
5426  *  \throw If \a this->getMeshDimension() < 1.
5427  */
5428 bool MEDCouplingUMesh::areOnlySimplexCells() const
5429 {
5430   checkFullyDefined();
5431   int mdim=getMeshDimension();
5432   if(mdim<1 || mdim>3)
5433     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5434   int nbCells=getNumberOfCells();
5435   const int *conn=_nodal_connec->getConstPointer();
5436   const int *connI=_nodal_connec_index->getConstPointer();
5437   for(int i=0;i<nbCells;i++)
5438     {
5439       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5440       if(!cm.isSimplex())
5441         return false;
5442     }
5443   return true;
5444 }
5445
5446 /*!
5447  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5448  */
5449 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5450 {
5451   checkConnectivityFullyDefined();
5452   if(getMeshDimension()!=2)
5453     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5454   int nbOfCells=getNumberOfCells();
5455   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5456   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5457   ret->alloc(nbOfCells+nbOfCutCells,1);
5458   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5459   int *retPt=ret->getPointer();
5460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5461   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5462   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5463   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5464   int *pt=newConn->getPointer();
5465   int *ptI=newConnI->getPointer();
5466   ptI[0]=0;
5467   const int *oldc=_nodal_connec->getConstPointer();
5468   const int *ci=_nodal_connec_index->getConstPointer();
5469   for(int i=0;i<nbOfCells;i++,ci++)
5470     {
5471       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5472         {
5473           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5474                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5475           pt=std::copy(tmp,tmp+8,pt);
5476           ptI[1]=ptI[0]+4;
5477           ptI[2]=ptI[0]+8;
5478           *retPt++=i;
5479           *retPt++=i;
5480           ptI+=2;
5481         }
5482       else
5483         {
5484           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5485           ptI[1]=ptI[0]+ci[1]-ci[0];
5486           ptI++;
5487           *retPt++=i;
5488         }
5489     }
5490   _nodal_connec->decrRef();
5491   _nodal_connec=newConn.retn();
5492   _nodal_connec_index->decrRef();
5493   _nodal_connec_index=newConnI.retn();
5494   computeTypes();
5495   updateTime();
5496   return ret.retn();
5497 }
5498
5499 /*!
5500  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5501  */
5502 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5503 {
5504   checkConnectivityFullyDefined();
5505   if(getMeshDimension()!=2)
5506     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5507   int nbOfCells=getNumberOfCells();
5508   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5509   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5510   ret->alloc(nbOfCells+nbOfCutCells,1);
5511   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5512   int *retPt=ret->getPointer();
5513   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5515   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5516   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5517   int *pt=newConn->getPointer();
5518   int *ptI=newConnI->getPointer();
5519   ptI[0]=0;
5520   const int *oldc=_nodal_connec->getConstPointer();
5521   const int *ci=_nodal_connec_index->getConstPointer();
5522   for(int i=0;i<nbOfCells;i++,ci++)
5523     {
5524       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5525         {
5526           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5527                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5528           pt=std::copy(tmp,tmp+8,pt);
5529           ptI[1]=ptI[0]+4;
5530           ptI[2]=ptI[0]+8;
5531           *retPt++=i;
5532           *retPt++=i;
5533           ptI+=2;
5534         }
5535       else
5536         {
5537           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5538           ptI[1]=ptI[0]+ci[1]-ci[0];
5539           ptI++;
5540           *retPt++=i;
5541         }
5542     }
5543   _nodal_connec->decrRef();
5544   _nodal_connec=newConn.retn();
5545   _nodal_connec_index->decrRef();
5546   _nodal_connec_index=newConnI.retn();
5547   computeTypes();
5548   updateTime();
5549   return ret.retn();
5550 }
5551
5552 /*!
5553  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5554  */
5555 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5556 {
5557   checkConnectivityFullyDefined();
5558   if(getMeshDimension()!=3)
5559     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5560   int nbOfCells=getNumberOfCells();
5561   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5562   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5563   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5564   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5565   int *retPt=ret->getPointer();
5566   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5567   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5568   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5569   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5570   int *pt=newConn->getPointer();
5571   int *ptI=newConnI->getPointer();
5572   ptI[0]=0;
5573   const int *oldc=_nodal_connec->getConstPointer();
5574   const int *ci=_nodal_connec_index->getConstPointer();
5575   for(int i=0;i<nbOfCells;i++,ci++)
5576     {
5577       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5578         {
5579           for(int j=0;j<5;j++,pt+=5,ptI++)
5580             {
5581               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5582               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];
5583               *retPt++=i;
5584               ptI[1]=ptI[0]+5;
5585             }
5586         }
5587       else
5588         {
5589           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5590           ptI[1]=ptI[0]+ci[1]-ci[0];
5591           ptI++;
5592           *retPt++=i;
5593         }
5594     }
5595   _nodal_connec->decrRef();
5596   _nodal_connec=newConn.retn();
5597   _nodal_connec_index->decrRef();
5598   _nodal_connec_index=newConnI.retn();
5599   computeTypes();
5600   updateTime();
5601   return ret.retn();
5602 }
5603
5604 /*!
5605  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5606  */
5607 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5608 {
5609   checkConnectivityFullyDefined();
5610   if(getMeshDimension()!=3)
5611     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5612   int nbOfCells=getNumberOfCells();
5613   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5614   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5615   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5616   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5617   int *retPt=ret->getPointer();
5618   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5619   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5620   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5621   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5622   int *pt=newConn->getPointer();
5623   int *ptI=newConnI->getPointer();
5624   ptI[0]=0;
5625   const int *oldc=_nodal_connec->getConstPointer();
5626   const int *ci=_nodal_connec_index->getConstPointer();
5627   for(int i=0;i<nbOfCells;i++,ci++)
5628     {
5629       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5630         {
5631           for(int j=0;j<6;j++,pt+=5,ptI++)
5632             {
5633               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5634               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];
5635               *retPt++=i;
5636               ptI[1]=ptI[0]+5;
5637             }
5638         }
5639       else
5640         {
5641           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5642           ptI[1]=ptI[0]+ci[1]-ci[0];
5643           ptI++;
5644           *retPt++=i;
5645         }
5646     }
5647   _nodal_connec->decrRef();
5648   _nodal_connec=newConn.retn();
5649   _nodal_connec_index->decrRef();
5650   _nodal_connec_index=newConnI.retn();
5651   computeTypes();
5652   updateTime();
5653   return ret.retn();
5654 }
5655
5656 /*!
5657  * 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.
5658  * This method completly ignore coordinates.
5659  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5660  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5661  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5662  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5663  */
5664 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5665 {
5666   checkFullyDefined();
5667   if(getMeshDimension()!=2)
5668     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5669   int nbOfCells=getNumberOfCells();
5670   int *connI=_nodal_connec_index->getPointer();
5671   int newConnLgth=0;
5672   for(int i=0;i<nbOfCells;i++,connI++)
5673     {
5674       int offset=descIndex[i];
5675       int nbOfEdges=descIndex[i+1]-offset;
5676       //
5677       bool ddirect=desc[offset+nbOfEdges-1]>0;
5678       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5679       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5680       for(int j=0;j<nbOfEdges;j++)
5681         {
5682           bool direct=desc[offset+j]>0;
5683           int edgeId=std::abs(desc[offset+j])-1;
5684           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5685             {
5686               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5687               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5688               int ref2=direct?id1:id2;
5689               if(ref==ref2)
5690                 {
5691                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5692                   newConnLgth+=nbOfSubNodes-1;
5693                   ref=direct?id2:id1;
5694                 }
5695               else
5696                 {
5697                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5698                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5699                 }
5700             }
5701           else
5702             {
5703               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5704             }
5705         }
5706       newConnLgth++;//+1 is for cell type
5707       connI[1]=newConnLgth;
5708     }
5709   //
5710   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5711   newConn->alloc(newConnLgth,1);
5712   int *work=newConn->getPointer();
5713   for(int i=0;i<nbOfCells;i++)
5714     {
5715       *work++=INTERP_KERNEL::NORM_POLYGON;
5716       int offset=descIndex[i];
5717       int nbOfEdges=descIndex[i+1]-offset;
5718       for(int j=0;j<nbOfEdges;j++)
5719         {
5720           bool direct=desc[offset+j]>0;
5721           int edgeId=std::abs(desc[offset+j])-1;
5722           if(direct)
5723             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5724           else
5725             {
5726               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5727               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5728               work=std::copy(it,it+nbOfSubNodes-1,work);
5729             }
5730         }
5731     }
5732   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5733   _types.clear();
5734   if(nbOfCells>0)
5735     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5736 }
5737
5738 /*!
5739  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5740  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5741  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5742  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5743  * so it can be useful to call mergeNodes() before calling this method.
5744  *  \throw If \a this->getMeshDimension() <= 1.
5745  *  \throw If the coordinates array is not set.
5746  *  \throw If the nodal connectivity of cells is not defined.
5747  */
5748 void MEDCouplingUMesh::convertDegeneratedCells()
5749 {
5750   checkFullyDefined();
5751   if(getMeshDimension()<=1)
5752     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5753   int nbOfCells=getNumberOfCells();
5754   if(nbOfCells<1)
5755     return ;
5756   int initMeshLgth=getMeshLength();
5757   int *conn=_nodal_connec->getPointer();
5758   int *index=_nodal_connec_index->getPointer();
5759   int posOfCurCell=0;
5760   int newPos=0;
5761   int lgthOfCurCell;
5762   for(int i=0;i<nbOfCells;i++)
5763     {
5764       lgthOfCurCell=index[i+1]-posOfCurCell;
5765       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5766       int newLgth;
5767       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5768                                                                                                      conn+newPos+1,newLgth);
5769       conn[newPos]=newType;
5770       newPos+=newLgth+1;
5771       posOfCurCell=index[i+1];
5772       index[i+1]=newPos;
5773     }
5774   if(newPos!=initMeshLgth)
5775     _nodal_connec->reAlloc(newPos);
5776   computeTypes();
5777 }
5778
5779 /*!
5780  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5781  * A cell is considered to be oriented correctly if an angle between its
5782  * normal vector and a given vector is less than \c PI / \c 2.
5783  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5784  *         cells. 
5785  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5786  *         checked.
5787  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5788  *         is not cleared before filling in.
5789  *  \throw If \a this->getMeshDimension() != 2.
5790  *  \throw If \a this->getSpaceDimension() != 3.
5791  *
5792  *  \if ENABLE_EXAMPLES
5793  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5794  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5795  *  \endif
5796  */
5797 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5798 {
5799   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5800     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5801   int nbOfCells=getNumberOfCells();
5802   const int *conn=_nodal_connec->getConstPointer();
5803   const int *connI=_nodal_connec_index->getConstPointer();
5804   const double *coordsPtr=_coords->getConstPointer();
5805   for(int i=0;i<nbOfCells;i++)
5806     {
5807       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5808       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5809         {
5810           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5811           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5812             cells.push_back(i);
5813         }
5814     }
5815 }
5816
5817 /*!
5818  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5819  * considered to be oriented correctly if an angle between its normal vector and a
5820  * given vector is less than \c PI / \c 2. 
5821  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5822  *         cells. 
5823  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5824  *         checked.
5825  *  \throw If \a this->getMeshDimension() != 2.
5826  *  \throw If \a this->getSpaceDimension() != 3.
5827  *
5828  *  \if ENABLE_EXAMPLES
5829  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5830  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5831  *  \endif
5832  */
5833 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5834 {
5835   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5836     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5837   int nbOfCells=getNumberOfCells();
5838   int *conn=_nodal_connec->getPointer();
5839   const int *connI=_nodal_connec_index->getConstPointer();
5840   const double *coordsPtr=_coords->getConstPointer();
5841   bool isModified=false;
5842   for(int i=0;i<nbOfCells;i++)
5843     {
5844       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5845       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5846         {
5847           bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5848           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5849             {
5850               isModified=true;
5851               if(!isQuadratic)
5852                 {
5853                   std::vector<int> tmp(connI[i+1]-connI[i]-2);
5854                   std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5855                   std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5856                 }
5857               else
5858                 {
5859                   int sz(((int)(connI[i+1]-connI[i]-1))/2);
5860                   std::vector<int> tmp0(sz-1),tmp1(sz);
5861                   std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5862                   std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5863                   std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5864                   std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5865                 }
5866             }
5867         }
5868     }
5869   if(isModified)
5870     _nodal_connec->declareAsNew();
5871   updateTime();
5872 }
5873
5874 /*!
5875  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5876  * oriented facets. The normal vector of the facet should point out of the cell.
5877  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5878  *         is not cleared before filling in.
5879  *  \throw If \a this->getMeshDimension() != 3.
5880  *  \throw If \a this->getSpaceDimension() != 3.
5881  *  \throw If the coordinates array is not set.
5882  *  \throw If the nodal connectivity of cells is not defined.
5883  *
5884  *  \if ENABLE_EXAMPLES
5885  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5886  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5887  *  \endif
5888  */
5889 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5890 {
5891   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5892     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5893   int nbOfCells=getNumberOfCells();
5894   const int *conn=_nodal_connec->getConstPointer();
5895   const int *connI=_nodal_connec_index->getConstPointer();
5896   const double *coordsPtr=_coords->getConstPointer();
5897   for(int i=0;i<nbOfCells;i++)
5898     {
5899       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5900       if(type==INTERP_KERNEL::NORM_POLYHED)
5901         {
5902           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5903             cells.push_back(i);
5904         }
5905     }
5906 }
5907
5908 /*!
5909  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5910  * out of the cell. 
5911  *  \throw If \a this->getMeshDimension() != 3.
5912  *  \throw If \a this->getSpaceDimension() != 3.
5913  *  \throw If the coordinates array is not set.
5914  *  \throw If the nodal connectivity of cells is not defined.
5915  *  \throw If the reparation fails.
5916  *
5917  *  \if ENABLE_EXAMPLES
5918  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5919  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5920  *  \endif
5921  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5922  */
5923 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5924 {
5925   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5926     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5927   int nbOfCells=getNumberOfCells();
5928   int *conn=_nodal_connec->getPointer();
5929   const int *connI=_nodal_connec_index->getConstPointer();
5930   const double *coordsPtr=_coords->getConstPointer();
5931   for(int i=0;i<nbOfCells;i++)
5932     {
5933       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5934       if(type==INTERP_KERNEL::NORM_POLYHED)
5935         {
5936           try
5937             {
5938               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5939                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5940             }
5941           catch(INTERP_KERNEL::Exception& e)
5942             {
5943               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5944               throw INTERP_KERNEL::Exception(oss.str().c_str());
5945             }
5946         }
5947     }
5948   updateTime();
5949 }
5950
5951 /*!
5952  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5953  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5954  * according to which the first facet of the cell should be oriented to have the normal vector
5955  * pointing out of cell.
5956  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5957  *         cells. The caller is to delete this array using decrRef() as it is no more
5958  *         needed. 
5959  *  \throw If \a this->getMeshDimension() != 3.
5960  *  \throw If \a this->getSpaceDimension() != 3.
5961  *  \throw If the coordinates array is not set.
5962  *  \throw If the nodal connectivity of cells is not defined.
5963  *
5964  *  \if ENABLE_EXAMPLES
5965  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5966  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5967  *  \endif
5968  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5969  */
5970 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5971 {
5972   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5973   if(getMeshDimension()!=3)
5974     throw INTERP_KERNEL::Exception(msg);
5975   int spaceDim=getSpaceDimension();
5976   if(spaceDim!=3)
5977     throw INTERP_KERNEL::Exception(msg);
5978   //
5979   int nbOfCells=getNumberOfCells();
5980   int *conn=_nodal_connec->getPointer();
5981   const int *connI=_nodal_connec_index->getConstPointer();
5982   const double *coo=getCoords()->getConstPointer();
5983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5984   for(int i=0;i<nbOfCells;i++)
5985     {
5986       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5987       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5988         {
5989           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5990             {
5991               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5992               cells->pushBackSilent(i);
5993             }
5994         }
5995     }
5996   return cells.retn();
5997 }
5998
5999 /*!
6000  * This method is a faster method to correct orientation of all 3D cells in \a this.
6001  * 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.
6002  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6003  * 
6004  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6005  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6006  */
6007 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6008 {
6009   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6010     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6011   int nbOfCells=getNumberOfCells();
6012   int *conn=_nodal_connec->getPointer();
6013   const int *connI=_nodal_connec_index->getConstPointer();
6014   const double *coordsPtr=_coords->getConstPointer();
6015   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6016   for(int i=0;i<nbOfCells;i++)
6017     {
6018       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6019       switch(type)
6020         {
6021         case INTERP_KERNEL::NORM_TETRA4:
6022           {
6023             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6024               {
6025                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6026                 ret->pushBackSilent(i);
6027               }
6028             break;
6029           }
6030         case INTERP_KERNEL::NORM_PYRA5:
6031           {
6032             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6033               {
6034                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6035                 ret->pushBackSilent(i);
6036               }
6037             break;
6038           }
6039         case INTERP_KERNEL::NORM_PENTA6:
6040         case INTERP_KERNEL::NORM_HEXA8:
6041         case INTERP_KERNEL::NORM_HEXGP12:
6042           {
6043             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6044               {
6045                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6046                 ret->pushBackSilent(i);
6047               }
6048             break;
6049           }
6050         case INTERP_KERNEL::NORM_POLYHED:
6051           {
6052             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6053               {
6054                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6055                 ret->pushBackSilent(i);
6056               }
6057             break;
6058           }
6059         default:
6060           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 !");
6061         }
6062     }
6063   updateTime();
6064   return ret.retn();
6065 }
6066
6067 /*!
6068  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6069  * If it is not the case an exception will be thrown.
6070  * This method is fast because the first cell of \a this is used to compute the plane.
6071  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6072  * \param pos output of size at least 3 used to store a point owned of searched plane.
6073  */
6074 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6075 {
6076   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6077     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6078   const int *conn=_nodal_connec->getConstPointer();
6079   const int *connI=_nodal_connec_index->getConstPointer();
6080   const double *coordsPtr=_coords->getConstPointer();
6081   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6082   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6083 }
6084
6085 /*!
6086  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6087  * cells. Currently cells of the following types are treated:
6088  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6089  * For a cell of other type an exception is thrown.
6090  * Space dimension of a 2D mesh can be either 2 or 3.
6091  * The Edge Ratio of a cell \f$t\f$ is: 
6092  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6093  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6094  *  the smallest edge lengths of \f$t\f$.
6095  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6096  *          cells and one time, lying on \a this mesh. The caller is to delete this
6097  *          field using decrRef() as it is no more needed. 
6098  *  \throw If the coordinates array is not set.
6099  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6100  *  \throw If the connectivity data array has more than one component.
6101  *  \throw If the connectivity data array has a named component.
6102  *  \throw If the connectivity index data array has more than one component.
6103  *  \throw If the connectivity index data array has a named component.
6104  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6105  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6106  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6107  */
6108 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6109 {
6110   checkCoherency();
6111   int spaceDim=getSpaceDimension();
6112   int meshDim=getMeshDimension();
6113   if(spaceDim!=2 && spaceDim!=3)
6114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6115   if(meshDim!=2 && meshDim!=3)
6116     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6117   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6118   ret->setMesh(this);
6119   int nbOfCells=getNumberOfCells();
6120   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6121   arr->alloc(nbOfCells,1);
6122   double *pt=arr->getPointer();
6123   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6124   const int *conn=_nodal_connec->getConstPointer();
6125   const int *connI=_nodal_connec_index->getConstPointer();
6126   const double *coo=_coords->getConstPointer();
6127   double tmp[12];
6128   for(int i=0;i<nbOfCells;i++,pt++)
6129     {
6130       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6131       switch(t)
6132         {
6133           case INTERP_KERNEL::NORM_TRI3:
6134             {
6135               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6136               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6137               break;
6138             }
6139           case INTERP_KERNEL::NORM_QUAD4:
6140             {
6141               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6142               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6143               break;
6144             }
6145           case INTERP_KERNEL::NORM_TETRA4:
6146             {
6147               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6148               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6149               break;
6150             }
6151         default:
6152           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6153         }
6154       conn+=connI[i+1]-connI[i];
6155     }
6156   ret->setName("EdgeRatio");
6157   ret->synchronizeTimeWithSupport();
6158   return ret.retn();
6159 }
6160
6161 /*!
6162  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6163  * cells. Currently cells of the following types are treated:
6164  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6165  * For a cell of other type an exception is thrown.
6166  * Space dimension of a 2D mesh can be either 2 or 3.
6167  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6168  *          cells and one time, lying on \a this mesh. The caller is to delete this
6169  *          field using decrRef() as it is no more needed. 
6170  *  \throw If the coordinates array is not set.
6171  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6172  *  \throw If the connectivity data array has more than one component.
6173  *  \throw If the connectivity data array has a named component.
6174  *  \throw If the connectivity index data array has more than one component.
6175  *  \throw If the connectivity index data array has a named component.
6176  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6177  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6178  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6179  */
6180 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6181 {
6182   checkCoherency();
6183   int spaceDim=getSpaceDimension();
6184   int meshDim=getMeshDimension();
6185   if(spaceDim!=2 && spaceDim!=3)
6186     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6187   if(meshDim!=2 && meshDim!=3)
6188     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6189   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6190   ret->setMesh(this);
6191   int nbOfCells=getNumberOfCells();
6192   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6193   arr->alloc(nbOfCells,1);
6194   double *pt=arr->getPointer();
6195   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6196   const int *conn=_nodal_connec->getConstPointer();
6197   const int *connI=_nodal_connec_index->getConstPointer();
6198   const double *coo=_coords->getConstPointer();
6199   double tmp[12];
6200   for(int i=0;i<nbOfCells;i++,pt++)
6201     {
6202       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6203       switch(t)
6204         {
6205           case INTERP_KERNEL::NORM_TRI3:
6206             {
6207               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6208               *pt=INTERP_KERNEL::triAspectRatio(tmp);
6209               break;
6210             }
6211           case INTERP_KERNEL::NORM_QUAD4:
6212             {
6213               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6214               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6215               break;
6216             }
6217           case INTERP_KERNEL::NORM_TETRA4:
6218             {
6219               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6220               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6221               break;
6222             }
6223         default:
6224           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6225         }
6226       conn+=connI[i+1]-connI[i];
6227     }
6228   ret->setName("AspectRatio");
6229   ret->synchronizeTimeWithSupport();
6230   return ret.retn();
6231 }
6232
6233 /*!
6234  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6235  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6236  * treated: INTERP_KERNEL::NORM_QUAD4.
6237  * For a cell of other type an exception is thrown.
6238  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6239  *          cells and one time, lying on \a this mesh. The caller is to delete this
6240  *          field using decrRef() as it is no more needed. 
6241  *  \throw If the coordinates array is not set.
6242  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6243  *  \throw If the connectivity data array has more than one component.
6244  *  \throw If the connectivity data array has a named component.
6245  *  \throw If the connectivity index data array has more than one component.
6246  *  \throw If the connectivity index data array has a named component.
6247  *  \throw If \a this->getMeshDimension() != 2.
6248  *  \throw If \a this->getSpaceDimension() != 3.
6249  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6250  */
6251 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6252 {
6253   checkCoherency();
6254   int spaceDim=getSpaceDimension();
6255   int meshDim=getMeshDimension();
6256   if(spaceDim!=3)
6257     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6258   if(meshDim!=2)
6259     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6260   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6261   ret->setMesh(this);
6262   int nbOfCells=getNumberOfCells();
6263   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6264   arr->alloc(nbOfCells,1);
6265   double *pt=arr->getPointer();
6266   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6267   const int *conn=_nodal_connec->getConstPointer();
6268   const int *connI=_nodal_connec_index->getConstPointer();
6269   const double *coo=_coords->getConstPointer();
6270   double tmp[12];
6271   for(int i=0;i<nbOfCells;i++,pt++)
6272     {
6273       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6274       switch(t)
6275         {
6276           case INTERP_KERNEL::NORM_QUAD4:
6277             {
6278               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6279               *pt=INTERP_KERNEL::quadWarp(tmp);
6280               break;
6281             }
6282         default:
6283           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6284         }
6285       conn+=connI[i+1]-connI[i];
6286     }
6287   ret->setName("Warp");
6288   ret->synchronizeTimeWithSupport();
6289   return ret.retn();
6290 }
6291
6292
6293 /*!
6294  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6295  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6296  * treated: INTERP_KERNEL::NORM_QUAD4.
6297  * For a cell of other type an exception is thrown.
6298  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6299  *          cells and one time, lying on \a this mesh. The caller is to delete this
6300  *          field using decrRef() as it is no more needed. 
6301  *  \throw If the coordinates array is not set.
6302  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6303  *  \throw If the connectivity data array has more than one component.
6304  *  \throw If the connectivity data array has a named component.
6305  *  \throw If the connectivity index data array has more than one component.
6306  *  \throw If the connectivity index data array has a named component.
6307  *  \throw If \a this->getMeshDimension() != 2.
6308  *  \throw If \a this->getSpaceDimension() != 3.
6309  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6310  */
6311 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6312 {
6313   checkCoherency();
6314   int spaceDim=getSpaceDimension();
6315   int meshDim=getMeshDimension();
6316   if(spaceDim!=3)
6317     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6318   if(meshDim!=2)
6319     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6320   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6321   ret->setMesh(this);
6322   int nbOfCells=getNumberOfCells();
6323   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6324   arr->alloc(nbOfCells,1);
6325   double *pt=arr->getPointer();
6326   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6327   const int *conn=_nodal_connec->getConstPointer();
6328   const int *connI=_nodal_connec_index->getConstPointer();
6329   const double *coo=_coords->getConstPointer();
6330   double tmp[12];
6331   for(int i=0;i<nbOfCells;i++,pt++)
6332     {
6333       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6334       switch(t)
6335         {
6336           case INTERP_KERNEL::NORM_QUAD4:
6337             {
6338               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6339               *pt=INTERP_KERNEL::quadSkew(tmp);
6340               break;
6341             }
6342         default:
6343           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6344         }
6345       conn+=connI[i+1]-connI[i];
6346     }
6347   ret->setName("Skew");
6348   ret->synchronizeTimeWithSupport();
6349   return ret.retn();
6350 }
6351
6352 /*!
6353  * This method aggregate the bbox of each cell and put it into bbox parameter.
6354  * 
6355  * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6356  *                         For all other cases this input parameter is ignored.
6357  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6358  * 
6359  * \throw If \a this is not fully set (coordinates and connectivity).
6360  * \throw If a cell in \a this has no valid nodeId.
6361  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6362  */
6363 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6364 {
6365   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6366   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.
6367     return getBoundingBoxForBBTreeFast();
6368   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6369     {
6370       bool presenceOfQuadratic(false);
6371       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6372         {
6373           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6374           if(cm.isQuadratic())
6375             presenceOfQuadratic=true;
6376         }
6377       if(!presenceOfQuadratic)
6378         return getBoundingBoxForBBTreeFast();
6379       if(mDim==2 && sDim==2)
6380         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6381       else
6382         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6383     }
6384   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) !");
6385 }
6386
6387 /*!
6388  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6389  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6390  * 
6391  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6392  * 
6393  * \throw If \a this is not fully set (coordinates and connectivity).
6394  * \throw If a cell in \a this has no valid nodeId.
6395  */
6396 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6397 {
6398   checkFullyDefined();
6399   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6400   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6401   double *bbox(ret->getPointer());
6402   for(int i=0;i<nbOfCells*spaceDim;i++)
6403     {
6404       bbox[2*i]=std::numeric_limits<double>::max();
6405       bbox[2*i+1]=-std::numeric_limits<double>::max();
6406     }
6407   const double *coordsPtr(_coords->getConstPointer());
6408   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6409   for(int i=0;i<nbOfCells;i++)
6410     {
6411       int offset=connI[i]+1;
6412       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6413       for(int j=0;j<nbOfNodesForCell;j++)
6414         {
6415           int nodeId=conn[offset+j];
6416           if(nodeId>=0 && nodeId<nbOfNodes)
6417             {
6418               for(int k=0;k<spaceDim;k++)
6419                 {
6420                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6421                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6422                 }
6423               kk++;
6424             }
6425         }
6426       if(kk==0)
6427         {
6428           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6429           throw INTERP_KERNEL::Exception(oss.str().c_str());
6430         }
6431     }
6432   return ret.retn();
6433 }
6434
6435 /*!
6436  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6437  * useful for 2D meshes having quadratic cells
6438  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6439  * the two extremities of the arc of circle).
6440  * 
6441  * \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)
6442  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6443  * \throw If \a this is not fully defined.
6444  * \throw If \a this is not a mesh with meshDimension equal to 2.
6445  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6446  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6447  */
6448 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6449 {
6450   checkFullyDefined();
6451   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6452   if(spaceDim!=2 || mDim!=2)
6453     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!");
6454   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6455   double *bbox(ret->getPointer());
6456   const double *coords(_coords->getConstPointer());
6457   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6458   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6459     {
6460       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6461       int sz(connI[1]-connI[0]-1);
6462       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6463       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6464       INTERP_KERNEL::QuadraticPolygon *pol(0);
6465       for(int j=0;j<sz;j++)
6466         {
6467           int nodeId(conn[*connI+1+j]);
6468           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6469         }
6470       if(!cm.isQuadratic())
6471         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6472       else
6473         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6474       INTERP_KERNEL::Bounds b; pol->fillBounds(b); delete pol;
6475       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6476     }
6477   return ret.retn();
6478 }
6479
6480 /*!
6481  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6482  * useful for 2D meshes having quadratic cells
6483  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6484  * the two extremities of the arc of circle).
6485  * 
6486  * \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)
6487  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6488  * \throw If \a this is not fully defined.
6489  * \throw If \a this is not a mesh with meshDimension equal to 1.
6490  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6491  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6492  */
6493 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6494 {
6495   checkFullyDefined();
6496   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6497   if(spaceDim!=2 || mDim!=1)
6498     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!");
6499   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6500   double *bbox(ret->getPointer());
6501   const double *coords(_coords->getConstPointer());
6502   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6503   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6504     {
6505       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6506       int sz(connI[1]-connI[0]-1);
6507       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6508       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6509       INTERP_KERNEL::Edge *edge(0);
6510       for(int j=0;j<sz;j++)
6511         {
6512           int nodeId(conn[*connI+1+j]);
6513           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6514         }
6515       if(!cm.isQuadratic())
6516         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6517       else
6518         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6519       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6520       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6521     }
6522   return ret.retn();
6523 }
6524
6525 /// @cond INTERNAL
6526
6527 namespace ParaMEDMEMImpl
6528 {
6529   class ConnReader
6530   {
6531   public:
6532     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6533     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6534   private:
6535     const int *_conn;
6536     int _val;
6537   };
6538
6539   class ConnReader2
6540   {
6541   public:
6542     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6543     bool operator() (const int& pos) { return _conn[pos]==_val; }
6544   private:
6545     const int *_conn;
6546     int _val;
6547   };
6548 }
6549
6550 /// @endcond
6551
6552 /*!
6553  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6554  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6555  * \a this is composed in cell types.
6556  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6557  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6558  * This parameter is kept only for compatibility with other methode listed above.
6559  */
6560 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6561 {
6562   checkConnectivityFullyDefined();
6563   const int *conn=_nodal_connec->getConstPointer();
6564   const int *connI=_nodal_connec_index->getConstPointer();
6565   const int *work=connI;
6566   int nbOfCells=getNumberOfCells();
6567   std::size_t n=getAllGeoTypes().size();
6568   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6569   std::set<INTERP_KERNEL::NormalizedCellType> types;
6570   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6571     {
6572       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6573       if(types.find(typ)!=types.end())
6574         {
6575           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6576           oss << " is not contiguous !";
6577           throw INTERP_KERNEL::Exception(oss.str().c_str());
6578         }
6579       types.insert(typ);
6580       ret[3*i]=typ;
6581       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6582       ret[3*i+1]=(int)std::distance(work,work2);
6583       work=work2;
6584     }
6585   return ret;
6586 }
6587
6588 /*!
6589  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6590  * only for types cell, type node is not managed.
6591  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6592  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6593  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6594  * If 2 or more same geometric type is in \a code and exception is thrown too.
6595  *
6596  * This method firstly checks
6597  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6598  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6599  * an exception is thrown too.
6600  * 
6601  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6602  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6603  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6604  */
6605 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6606 {
6607   if(code.empty())
6608     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6609   std::size_t sz=code.size();
6610   std::size_t n=sz/3;
6611   if(sz%3!=0)
6612     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6613   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6614   int nb=0;
6615   bool isNoPflUsed=true;
6616   for(std::size_t i=0;i<n;i++)
6617     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6618       {
6619         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6620         nb+=code[3*i+1];
6621         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6622           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6623         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6624       }
6625   if(types.size()!=n)
6626     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6627   if(isNoPflUsed)
6628     {
6629       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6630         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6631       if(types.size()==_types.size())
6632         return 0;
6633     }
6634   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6635   ret->alloc(nb,1);
6636   int *retPtr=ret->getPointer();
6637   const int *connI=_nodal_connec_index->getConstPointer();
6638   const int *conn=_nodal_connec->getConstPointer();
6639   int nbOfCells=getNumberOfCells();
6640   const int *i=connI;
6641   int kk=0;
6642   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6643     {
6644       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6645       int offset=(int)std::distance(connI,i);
6646       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6647       int nbOfCellsOfCurType=(int)std::distance(i,j);
6648       if(code[3*kk+2]==-1)
6649         for(int k=0;k<nbOfCellsOfCurType;k++)
6650           *retPtr++=k+offset;
6651       else
6652         {
6653           int idInIdsPerType=code[3*kk+2];
6654           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6655             {
6656               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6657               if(zePfl)
6658                 {
6659                   zePfl->checkAllocated();
6660                   if(zePfl->getNumberOfComponents()==1)
6661                     {
6662                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6663                         {
6664                           if(*k>=0 && *k<nbOfCellsOfCurType)
6665                             *retPtr=(*k)+offset;
6666                           else
6667                             {
6668                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6669                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6670                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6671                             }
6672                         }
6673                     }
6674                   else
6675                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6676                 }
6677               else
6678                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6679             }
6680           else
6681             {
6682               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6683               oss << " should be in [0," << idsPerType.size() << ") !";
6684               throw INTERP_KERNEL::Exception(oss.str().c_str());
6685             }
6686         }
6687       i=j;
6688     }
6689   return ret.retn();
6690 }
6691
6692 /*!
6693  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6694  * 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.
6695  * 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.
6696  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6697  * 
6698  * \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.
6699  * \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,
6700  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6701  * \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.
6702  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6703  * \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
6704  */
6705 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6706 {
6707   if(!profile)
6708     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6709   if(profile->getNumberOfComponents()!=1)
6710     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6711   checkConnectivityFullyDefined();
6712   const int *conn=_nodal_connec->getConstPointer();
6713   const int *connI=_nodal_connec_index->getConstPointer();
6714   int nbOfCells=getNumberOfCells();
6715   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6716   std::vector<int> typeRangeVals(1);
6717   for(const int *i=connI;i!=connI+nbOfCells;)
6718     {
6719       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6720       if(std::find(types.begin(),types.end(),curType)!=types.end())
6721         {
6722           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6723         }
6724       types.push_back(curType);
6725       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6726       typeRangeVals.push_back((int)std::distance(connI,i));
6727     }
6728   //
6729   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6730   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6731   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6732   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6733   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6734   //
6735   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6736   code.resize(3*nbOfCastsFinal);
6737   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6738   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6739   for(int i=0;i<nbOfCastsFinal;i++)
6740     {
6741       int castId=castsPresent->getIJ(i,0);
6742       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6743       idsInPflPerType2.push_back(tmp3);
6744       code[3*i]=(int)types[castId];
6745       code[3*i+1]=tmp3->getNumberOfTuples();
6746       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6747       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6748         {
6749           tmp4->copyStringInfoFrom(*profile);
6750           idsPerType2.push_back(tmp4);
6751           code[3*i+2]=(int)idsPerType2.size()-1;
6752         }
6753       else
6754         {
6755           code[3*i+2]=-1;
6756         }
6757     }
6758   std::size_t sz2=idsInPflPerType2.size();
6759   idsInPflPerType.resize(sz2);
6760   for(std::size_t i=0;i<sz2;i++)
6761     {
6762       DataArrayInt *locDa=idsInPflPerType2[i];
6763       locDa->incrRef();
6764       idsInPflPerType[i]=locDa;
6765     }
6766   std::size_t sz=idsPerType2.size();
6767   idsPerType.resize(sz);
6768   for(std::size_t i=0;i<sz;i++)
6769     {
6770       DataArrayInt *locDa=idsPerType2[i];
6771       locDa->incrRef();
6772       idsPerType[i]=locDa;
6773     }
6774 }
6775
6776 /*!
6777  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6778  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6779  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6780  * 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.
6781  */
6782 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6783 {
6784   checkFullyDefined();
6785   nM1LevMesh->checkFullyDefined();
6786   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6787     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6788   if(_coords!=nM1LevMesh->getCoords())
6789     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6790   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6791   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6792   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6793   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6794   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6795   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6796   tmp->setConnectivity(tmp0,tmp1);
6797   tmp->renumberCells(ret0->getConstPointer(),false);
6798   revDesc=tmp->getNodalConnectivity();
6799   revDescIndx=tmp->getNodalConnectivityIndex();
6800   DataArrayInt *ret=0;
6801   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6802     {
6803       int tmp2;
6804       ret->getMaxValue(tmp2);
6805       ret->decrRef();
6806       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6807       throw INTERP_KERNEL::Exception(oss.str().c_str());
6808     }
6809   nM1LevMeshIds=ret;
6810   //
6811   revDesc->incrRef();
6812   revDescIndx->incrRef();
6813   ret1->incrRef();
6814   ret0->incrRef();
6815   meshnM1Old2New=ret0;
6816   return ret1;
6817 }
6818
6819 /*!
6820  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6821  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6822  * in "Old to New" mode.
6823  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6824  *          this array using decrRef() as it is no more needed.
6825  *  \throw If the nodal connectivity of cells is not defined.
6826  */
6827 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6828 {
6829   checkConnectivityFullyDefined();
6830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6831   renumberCells(ret->getConstPointer(),false);
6832   return ret.retn();
6833 }
6834
6835 /*!
6836  * This methods checks that cells are sorted by their types.
6837  * This method makes asumption (no check) that connectivity is correctly set before calling.
6838  */
6839 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6840 {
6841   checkFullyDefined();
6842   const int *conn=_nodal_connec->getConstPointer();
6843   const int *connI=_nodal_connec_index->getConstPointer();
6844   int nbOfCells=getNumberOfCells();
6845   std::set<INTERP_KERNEL::NormalizedCellType> types;
6846   for(const int *i=connI;i!=connI+nbOfCells;)
6847     {
6848       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6849       if(types.find(curType)!=types.end())
6850         return false;
6851       types.insert(curType);
6852       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6853     }
6854   return true;
6855 }
6856
6857 /*!
6858  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6859  * The geometric type order is specified by MED file.
6860  * 
6861  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6862  */
6863 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6864 {
6865   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6866 }
6867
6868 /*!
6869  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6870  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6871  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6872  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6873  */
6874 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6875 {
6876   checkFullyDefined();
6877   const int *conn=_nodal_connec->getConstPointer();
6878   const int *connI=_nodal_connec_index->getConstPointer();
6879   int nbOfCells=getNumberOfCells();
6880   if(nbOfCells==0)
6881     return true;
6882   int lastPos=-1;
6883   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6884   for(const int *i=connI;i!=connI+nbOfCells;)
6885     {
6886       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6887       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6888       if(isTypeExists!=orderEnd)
6889         {
6890           int pos=(int)std::distance(orderBg,isTypeExists);
6891           if(pos<=lastPos)
6892             return false;
6893           lastPos=pos;
6894           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6895         }
6896       else
6897         {
6898           if(sg.find(curType)==sg.end())
6899             {
6900               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6901               sg.insert(curType);
6902             }
6903           else
6904             return false;
6905         }
6906     }
6907   return true;
6908 }
6909
6910 /*!
6911  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6912  * 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
6913  * 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'.
6914  */
6915 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6916 {
6917   checkConnectivityFullyDefined();
6918   int nbOfCells=getNumberOfCells();
6919   const int *conn=_nodal_connec->getConstPointer();
6920   const int *connI=_nodal_connec_index->getConstPointer();
6921   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6922   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6923   tmpa->alloc(nbOfCells,1);
6924   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6925   tmpb->fillWithZero();
6926   int *tmp=tmpa->getPointer();
6927   int *tmp2=tmpb->getPointer();
6928   for(const int *i=connI;i!=connI+nbOfCells;i++)
6929     {
6930       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6931       if(where!=orderEnd)
6932         {
6933           int pos=(int)std::distance(orderBg,where);
6934           tmp2[pos]++;
6935           tmp[std::distance(connI,i)]=pos;
6936         }
6937       else
6938         {
6939           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6940           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6941           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6942           throw INTERP_KERNEL::Exception(oss.str().c_str());
6943         }
6944     }
6945   nbPerType=tmpb.retn();
6946   return tmpa.retn();
6947 }
6948
6949 /*!
6950  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6951  *
6952  * \return a new object containing the old to new correspondance.
6953  *
6954  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6955  */
6956 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6957 {
6958   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6959 }
6960
6961 /*!
6962  * 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.
6963  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6964  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6965  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6966  */
6967 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6968 {
6969   DataArrayInt *nbPerType=0;
6970   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6971   nbPerType->decrRef();
6972   return tmpa->buildPermArrPerLevel();
6973 }
6974
6975 /*!
6976  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6977  * The number of cells remains unchanged after the call of this method.
6978  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6979  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6980  *
6981  * \return the array giving the correspondance old to new.
6982  */
6983 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6984 {
6985   checkFullyDefined();
6986   computeTypes();
6987   const int *conn=_nodal_connec->getConstPointer();
6988   const int *connI=_nodal_connec_index->getConstPointer();
6989   int nbOfCells=getNumberOfCells();
6990   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6991   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6992     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6993       {
6994         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6995         types.push_back(curType);
6996         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6997       }
6998   DataArrayInt *ret=DataArrayInt::New();
6999   ret->alloc(nbOfCells,1);
7000   int *retPtr=ret->getPointer();
7001   std::fill(retPtr,retPtr+nbOfCells,-1);
7002   int newCellId=0;
7003   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7004     {
7005       for(const int *i=connI;i!=connI+nbOfCells;i++)
7006         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7007           retPtr[std::distance(connI,i)]=newCellId++;
7008     }
7009   renumberCells(retPtr,false);
7010   return ret;
7011 }
7012
7013 /*!
7014  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7015  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7016  * This method makes asumption that connectivity is correctly set before calling.
7017  */
7018 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7019 {
7020   checkConnectivityFullyDefined();
7021   const int *conn=_nodal_connec->getConstPointer();
7022   const int *connI=_nodal_connec_index->getConstPointer();
7023   int nbOfCells=getNumberOfCells();
7024   std::vector<MEDCouplingUMesh *> ret;
7025   for(const int *i=connI;i!=connI+nbOfCells;)
7026     {
7027       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7028       int beginCellId=(int)std::distance(connI,i);
7029       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7030       int endCellId=(int)std::distance(connI,i);
7031       int sz=endCellId-beginCellId;
7032       int *cells=new int[sz];
7033       for(int j=0;j<sz;j++)
7034         cells[j]=beginCellId+j;
7035       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7036       delete [] cells;
7037       ret.push_back(m);
7038     }
7039   return ret;
7040 }
7041
7042 /*!
7043  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7044  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7045  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7046  *
7047  * \return a newly allocated instance, that the caller must manage.
7048  * \throw If \a this contains more than one geometric type.
7049  * \throw If the nodal connectivity of \a this is not fully defined.
7050  * \throw If the internal data is not coherent.
7051  */
7052 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7053 {
7054   checkConnectivityFullyDefined();
7055     if(_types.size()!=1)
7056     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7057   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7058   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7059   ret->setCoords(getCoords());
7060   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7061   if(retC)
7062     {
7063       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7064       retC->setNodalConnectivity(c);
7065     }
7066   else
7067     {
7068       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7069       if(!retD)
7070         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7071       DataArrayInt *c=0,*ci=0;
7072       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7073       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7074       retD->setNodalConnectivity(cs,cis);
7075     }
7076   return ret.retn();
7077 }
7078
7079 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7080 {
7081   checkConnectivityFullyDefined();
7082     if(_types.size()!=1)
7083     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7084   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7085   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7086   if(cm.isDynamic())
7087     {
7088       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7089       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7090       throw INTERP_KERNEL::Exception(oss.str().c_str());
7091     }
7092   int nbCells=getNumberOfCells();
7093   int typi=(int)typ;
7094   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7095   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7096   int *outPtr=connOut->getPointer();
7097   const int *conn=_nodal_connec->begin();
7098   const int *connI=_nodal_connec_index->begin();
7099   nbNodesPerCell++;
7100   for(int i=0;i<nbCells;i++,connI++)
7101     {
7102       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7103         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7104       else
7105         {
7106           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 << ") !";
7107           throw INTERP_KERNEL::Exception(oss.str().c_str());
7108         }
7109     }
7110   return connOut.retn();
7111 }
7112
7113 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7114 {
7115   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7116   checkConnectivityFullyDefined();
7117   if(_types.size()!=1)
7118     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7119   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7120   if(lgth<nbCells)
7121     throw INTERP_KERNEL::Exception(msg0);
7122   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7123   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7124   int *cp(c->getPointer()),*cip(ci->getPointer());
7125   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7126   cip[0]=0;
7127   for(int i=0;i<nbCells;i++,cip++,incip++)
7128     {
7129       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7130       int delta(stop-strt);
7131       if(delta>=1)
7132         {
7133           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7134             cp=std::copy(incp+strt,incp+stop,cp);
7135           else
7136             throw INTERP_KERNEL::Exception(msg0);
7137         }
7138       else
7139         throw INTERP_KERNEL::Exception(msg0);
7140       cip[1]=cip[0]+delta;
7141     }
7142   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7143 }
7144
7145 /*!
7146  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7147  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7148  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7149  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7150  * are not used here to avoid the build of big permutation array.
7151  *
7152  * \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
7153  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7154  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7155  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7156  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7157  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7158  * \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
7159  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7160  */
7161 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7162                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7163                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
7164 {
7165   std::vector<const MEDCouplingUMesh *> ms2;
7166   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7167     if(*it)
7168       {
7169         (*it)->checkConnectivityFullyDefined();
7170         ms2.push_back(*it);
7171       }
7172   if(ms2.empty())
7173     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7174   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7175   int meshDim=ms2[0]->getMeshDimension();
7176   std::vector<const MEDCouplingUMesh *> m1ssm;
7177   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7178   //
7179   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7180   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7181   int fake=0,rk=0;
7182   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7183   ret1->alloc(0,1); ret2->alloc(0,1);
7184   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7185     {
7186       if(meshDim!=(*it)->getMeshDimension())
7187         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7188       if(refCoo!=(*it)->getCoords())
7189         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7190       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7191       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7192       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7193       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7194         {
7195           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7196           m1ssmSingleAuto.push_back(singleCell);
7197           m1ssmSingle.push_back(singleCell);
7198           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7199         }
7200     }
7201   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7202   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7203   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7204   for(std::size_t i=0;i<m1ssm.size();i++)
7205     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7206   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7207   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7208   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7209   return ret0.retn();
7210 }
7211
7212 /*!
7213  * This method returns a newly created DataArrayInt instance.
7214  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7215  */
7216 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7217 {
7218   checkFullyDefined();
7219   const int *conn=_nodal_connec->getConstPointer();
7220   const int *connIndex=_nodal_connec_index->getConstPointer();
7221   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7222   for(const int *w=begin;w!=end;w++)
7223     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7224       ret->pushBackSilent(*w);
7225   return ret.retn();
7226 }
7227
7228 /*!
7229  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7230  * are in [0:getNumberOfCells())
7231  */
7232 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7233 {
7234   checkFullyDefined();
7235   const int *conn=_nodal_connec->getConstPointer();
7236   const int *connI=_nodal_connec_index->getConstPointer();
7237   int nbOfCells=getNumberOfCells();
7238   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7239   int *tmp=new int[nbOfCells];
7240   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7241     {
7242       int j=0;
7243       for(const int *i=connI;i!=connI+nbOfCells;i++)
7244         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7245           tmp[std::distance(connI,i)]=j++;
7246     }
7247   DataArrayInt *ret=DataArrayInt::New();
7248   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7249   ret->copyStringInfoFrom(*da);
7250   int *retPtr=ret->getPointer();
7251   const int *daPtr=da->getConstPointer();
7252   int nbOfElems=da->getNbOfElems();
7253   for(int k=0;k<nbOfElems;k++)
7254     retPtr[k]=tmp[daPtr[k]];
7255   delete [] tmp;
7256   return ret;
7257 }
7258
7259 /*!
7260  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7261  * This method \b works \b for mesh sorted by type.
7262  * cells whose ids is in 'idsPerGeoType' array.
7263  * This method conserves coords and name of mesh.
7264  */
7265 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7266 {
7267   std::vector<int> code=getDistributionOfTypes();
7268   std::size_t nOfTypesInThis=code.size()/3;
7269   int sz=0,szOfType=0;
7270   for(std::size_t i=0;i<nOfTypesInThis;i++)
7271     {
7272       if(code[3*i]!=type)
7273         sz+=code[3*i+1];
7274       else
7275         szOfType=code[3*i+1];
7276     }
7277   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7278     if(*work<0 || *work>=szOfType)
7279       {
7280         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7281         oss << ". It should be in [0," << szOfType << ") !";
7282         throw INTERP_KERNEL::Exception(oss.str().c_str());
7283       }
7284   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7285   int *idsPtr=idsTokeep->getPointer();
7286   int offset=0;
7287   for(std::size_t i=0;i<nOfTypesInThis;i++)
7288     {
7289       if(code[3*i]!=type)
7290         for(int j=0;j<code[3*i+1];j++)
7291           *idsPtr++=offset+j;
7292       else
7293         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7294       offset+=code[3*i+1];
7295     }
7296   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7297   ret->copyTinyInfoFrom(this);
7298   return ret.retn();
7299 }
7300
7301 /*!
7302  * This method returns a vector of size 'this->getNumberOfCells()'.
7303  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7304  */
7305 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7306 {
7307   int ncell=getNumberOfCells();
7308   std::vector<bool> ret(ncell);
7309   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7310   const int *c=getNodalConnectivity()->getConstPointer();
7311   for(int i=0;i<ncell;i++)
7312     {
7313       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7314       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7315       ret[i]=cm.isQuadratic();
7316     }
7317   return ret;
7318 }
7319
7320 /*!
7321  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7322  */
7323 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7324 {
7325   if(other->getType()!=UNSTRUCTURED)
7326     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7327   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7328   return MergeUMeshes(this,otherC);
7329 }
7330
7331 /*!
7332  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7333  * computed by averaging coordinates of cell nodes, so this method is not a right
7334  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7335  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7336  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7337  *          components. The caller is to delete this array using decrRef() as it is
7338  *          no more needed.
7339  *  \throw If the coordinates array is not set.
7340  *  \throw If the nodal connectivity of cells is not defined.
7341  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7342  */
7343 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7344 {
7345   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7346   int spaceDim=getSpaceDimension();
7347   int nbOfCells=getNumberOfCells();
7348   ret->alloc(nbOfCells,spaceDim);
7349   ret->copyStringInfoFrom(*getCoords());
7350   double *ptToFill=ret->getPointer();
7351   const int *nodal=_nodal_connec->getConstPointer();
7352   const int *nodalI=_nodal_connec_index->getConstPointer();
7353   const double *coor=_coords->getConstPointer();
7354   for(int i=0;i<nbOfCells;i++)
7355     {
7356       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7357       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7358       ptToFill+=spaceDim;
7359     }
7360   return ret.retn();
7361 }
7362
7363 /*!
7364  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7365  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7366  * 
7367  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7368  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7369  * 
7370  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7371  * \throw If \a this is not fully defined (coordinates and connectivity)
7372  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7373  */
7374 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7375 {
7376   checkFullyDefined();
7377   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7378   int spaceDim=getSpaceDimension();
7379   int nbOfCells=getNumberOfCells();
7380   int nbOfNodes=getNumberOfNodes();
7381   ret->alloc(nbOfCells,spaceDim);
7382   double *ptToFill=ret->getPointer();
7383   const int *nodal=_nodal_connec->getConstPointer();
7384   const int *nodalI=_nodal_connec_index->getConstPointer();
7385   const double *coor=_coords->getConstPointer();
7386   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7387     {
7388       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7389       std::fill(ptToFill,ptToFill+spaceDim,0.);
7390       if(type!=INTERP_KERNEL::NORM_POLYHED)
7391         {
7392           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7393             {
7394               if(*conn>=0 && *conn<nbOfNodes)
7395                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7396               else
7397                 {
7398                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7399                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7400                 }
7401             }
7402           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7403           if(nbOfNodesInCell>0)
7404             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7405           else
7406             {
7407               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7408               throw INTERP_KERNEL::Exception(oss.str().c_str());
7409             }
7410         }
7411       else
7412         {
7413           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7414           s.erase(-1);
7415           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7416             {
7417               if(*it>=0 && *it<nbOfNodes)
7418                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7419               else
7420                 {
7421                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7422                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7423                 }
7424             }
7425           if(!s.empty())
7426             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7427           else
7428             {
7429               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7430               throw INTERP_KERNEL::Exception(oss.str().c_str());
7431             }
7432         }
7433     }
7434   return ret.retn();
7435 }
7436
7437 /*!
7438  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7439  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7440  * are specified via an array of cell ids. 
7441  *  \warning Validity of the specified cell ids is not checked! 
7442  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7443  *  \param [in] begin - an array of cell ids of interest.
7444  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7445  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7446  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7447  *          caller is to delete this array using decrRef() as it is no more needed. 
7448  *  \throw If the coordinates array is not set.
7449  *  \throw If the nodal connectivity of cells is not defined.
7450  *
7451  *  \if ENABLE_EXAMPLES
7452  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7453  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7454  *  \endif
7455  */
7456 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7457 {
7458   DataArrayDouble *ret=DataArrayDouble::New();
7459   int spaceDim=getSpaceDimension();
7460   int nbOfTuple=(int)std::distance(begin,end);
7461   ret->alloc(nbOfTuple,spaceDim);
7462   double *ptToFill=ret->getPointer();
7463   double *tmp=new double[spaceDim];
7464   const int *nodal=_nodal_connec->getConstPointer();
7465   const int *nodalI=_nodal_connec_index->getConstPointer();
7466   const double *coor=_coords->getConstPointer();
7467   for(const int *w=begin;w!=end;w++)
7468     {
7469       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7470       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7471       ptToFill+=spaceDim;
7472     }
7473   delete [] tmp;
7474   return ret;
7475 }
7476
7477 /*!
7478  * 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".
7479  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7480  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7481  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7482  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7483  * 
7484  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7485  * \throw If spaceDim!=3 or meshDim!=2.
7486  * \throw If connectivity of \a this is invalid.
7487  * \throw If connectivity of a cell in \a this points to an invalid node.
7488  */
7489 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7490 {
7491   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7492   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7493   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7494     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7495   ret->alloc(nbOfCells,4);
7496   double *retPtr(ret->getPointer());
7497   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7498   const double *coor(_coords->begin());
7499   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7500     {
7501       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7502       if(nodalI[1]-nodalI[0]>=3)
7503         {
7504           for(int j=0;j<3;j++)
7505             {
7506               int nodeId(nodal[nodalI[0]+1+j]);
7507               if(nodeId>=0 && nodeId<nbOfNodes)
7508                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7509               else
7510                 {
7511                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7512                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7513                 }
7514             }
7515         }
7516       else
7517         {
7518           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7519           throw INTERP_KERNEL::Exception(oss.str().c_str());
7520         }
7521       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7522       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7523     }
7524   return ret.retn();
7525 }
7526
7527 /*!
7528  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7529  * 
7530  */
7531 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7532 {
7533   if(!da)
7534     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7535   da->checkAllocated();
7536   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7537   ret->setCoords(da);
7538   int nbOfTuples=da->getNumberOfTuples();
7539   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7540   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7541   c->alloc(2*nbOfTuples,1);
7542   cI->alloc(nbOfTuples+1,1);
7543   int *cp=c->getPointer();
7544   int *cip=cI->getPointer();
7545   *cip++=0;
7546   for(int i=0;i<nbOfTuples;i++)
7547     {
7548       *cp++=INTERP_KERNEL::NORM_POINT1;
7549       *cp++=i;
7550       *cip++=2*(i+1);
7551     }
7552   ret->setConnectivity(c,cI,true);
7553   return ret.retn();
7554 }
7555 /*!
7556  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7557  * Cells and nodes of
7558  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7559  *  \param [in] mesh1 - the first mesh.
7560  *  \param [in] mesh2 - the second mesh.
7561  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7562  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7563  *          is no more needed.
7564  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7565  *  \throw If the coordinates array is not set in none of the meshes.
7566  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7567  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7568  */
7569 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7570 {
7571   std::vector<const MEDCouplingUMesh *> tmp(2);
7572   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7573   return MergeUMeshes(tmp);
7574 }
7575
7576 /*!
7577  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7578  * Cells and nodes of
7579  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7580  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7581  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7582  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7583  *          is no more needed.
7584  *  \throw If \a a.size() == 0.
7585  *  \throw If \a a[ *i* ] == NULL.
7586  *  \throw If the coordinates array is not set in none of the meshes.
7587  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7588  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7589 */
7590 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7591 {
7592   std::size_t sz=a.size();
7593   if(sz==0)
7594     return MergeUMeshesLL(a);
7595   for(std::size_t ii=0;ii<sz;ii++)
7596     if(!a[ii])
7597       {
7598         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7599         throw INTERP_KERNEL::Exception(oss.str().c_str());
7600       }
7601   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7602   std::vector< const MEDCouplingUMesh * > aa(sz);
7603   int spaceDim=-3;
7604   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7605     {
7606       const MEDCouplingUMesh *cur=a[i];
7607       const DataArrayDouble *coo=cur->getCoords();
7608       if(coo)
7609         spaceDim=coo->getNumberOfComponents();
7610     }
7611   if(spaceDim==-3)
7612     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7613   for(std::size_t i=0;i<sz;i++)
7614     {
7615       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7616       aa[i]=bb[i];
7617     }
7618   return MergeUMeshesLL(aa);
7619 }
7620
7621 /// @cond INTERNAL
7622
7623 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7624 {
7625   if(a.empty())
7626     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7627   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7628   int meshDim=(*it)->getMeshDimension();
7629   int nbOfCells=(*it)->getNumberOfCells();
7630   int meshLgth=(*it++)->getMeshLength();
7631   for(;it!=a.end();it++)
7632     {
7633       if(meshDim!=(*it)->getMeshDimension())
7634         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7635       nbOfCells+=(*it)->getNumberOfCells();
7636       meshLgth+=(*it)->getMeshLength();
7637     }
7638   std::vector<const MEDCouplingPointSet *> aps(a.size());
7639   std::copy(a.begin(),a.end(),aps.begin());
7640   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7641   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7642   ret->setCoords(pts);
7643   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7644   c->alloc(meshLgth,1);
7645   int *cPtr=c->getPointer();
7646   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7647   cI->alloc(nbOfCells+1,1);
7648   int *cIPtr=cI->getPointer();
7649   *cIPtr++=0;
7650   int offset=0;
7651   int offset2=0;
7652   for(it=a.begin();it!=a.end();it++)
7653     {
7654       int curNbOfCell=(*it)->getNumberOfCells();
7655       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7656       const int *curC=(*it)->_nodal_connec->getConstPointer();
7657       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7658       for(int j=0;j<curNbOfCell;j++)
7659         {
7660           const int *src=curC+curCI[j];
7661           *cPtr++=*src++;
7662           for(;src!=curC+curCI[j+1];src++,cPtr++)
7663             {
7664               if(*src!=-1)
7665                 *cPtr=*src+offset2;
7666               else
7667                 *cPtr=-1;
7668             }
7669         }
7670       offset+=curCI[curNbOfCell];
7671       offset2+=(*it)->getNumberOfNodes();
7672     }
7673   //
7674   ret->setConnectivity(c,cI,true);
7675   return ret.retn();
7676 }
7677
7678 /// @endcond
7679
7680 /*!
7681  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7682  * dimension and sharing the node coordinates array.
7683  * All cells of the first mesh precede all cells of the second mesh
7684  * within the result mesh. 
7685  *  \param [in] mesh1 - the first mesh.
7686  *  \param [in] mesh2 - the second mesh.
7687  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7688  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7689  *          is no more needed.
7690  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7691  *  \throw If the meshes do not share the node coordinates array.
7692  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7693  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7694  */
7695 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7696 {
7697   std::vector<const MEDCouplingUMesh *> tmp(2);
7698   tmp[0]=mesh1; tmp[1]=mesh2;
7699   return MergeUMeshesOnSameCoords(tmp);
7700 }
7701
7702 /*!
7703  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7704  * dimension and sharing the node coordinates array.
7705  * All cells of the *i*-th mesh precede all cells of the
7706  * (*i*+1)-th mesh within the result mesh.
7707  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7708  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7709  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7710  *          is no more needed.
7711  *  \throw If \a a.size() == 0.
7712  *  \throw If \a a[ *i* ] == NULL.
7713  *  \throw If the meshes do not share the node coordinates array.
7714  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7715  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7716  */
7717 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7718 {
7719   if(meshes.empty())
7720     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7721   for(std::size_t ii=0;ii<meshes.size();ii++)
7722     if(!meshes[ii])
7723       {
7724         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7725         throw INTERP_KERNEL::Exception(oss.str().c_str());
7726       }
7727   const DataArrayDouble *coords=meshes.front()->getCoords();
7728   int meshDim=meshes.front()->getMeshDimension();
7729   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7730   int meshLgth=0;
7731   int meshIndexLgth=0;
7732   for(;iter!=meshes.end();iter++)
7733     {
7734       if(coords!=(*iter)->getCoords())
7735         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7736       if(meshDim!=(*iter)->getMeshDimension())
7737         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7738       meshLgth+=(*iter)->getMeshLength();
7739       meshIndexLgth+=(*iter)->getNumberOfCells();
7740     }
7741   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7742   nodal->alloc(meshLgth,1);
7743   int *nodalPtr=nodal->getPointer();
7744   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7745   nodalIndex->alloc(meshIndexLgth+1,1);
7746   int *nodalIndexPtr=nodalIndex->getPointer();
7747   int offset=0;
7748   for(iter=meshes.begin();iter!=meshes.end();iter++)
7749     {
7750       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7751       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7752       int nbOfCells=(*iter)->getNumberOfCells();
7753       int meshLgth2=(*iter)->getMeshLength();
7754       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7755       if(iter!=meshes.begin())
7756         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7757       else
7758         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7759       offset+=meshLgth2;
7760     }
7761   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7762   ret->setName("merge");
7763   ret->setMeshDimension(meshDim);
7764   ret->setConnectivity(nodal,nodalIndex,true);
7765   ret->setCoords(coords);
7766   return ret;
7767 }
7768
7769 /*!
7770  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7771  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7772  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7773  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7774  * New" mode are returned for each input mesh.
7775  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7776  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7777  *          valid values [0,1,2], see zipConnectivityTraducer().
7778  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7779  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7780  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7781  *          no more needed.
7782  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7783  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7784  *          is no more needed.
7785  *  \throw If \a meshes.size() == 0.
7786  *  \throw If \a meshes[ *i* ] == NULL.
7787  *  \throw If the meshes do not share the node coordinates array.
7788  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7789  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7790  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7791  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7792  */
7793 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7794 {
7795   //All checks are delegated to MergeUMeshesOnSameCoords
7796   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7797   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7798   corr.resize(meshes.size());
7799   std::size_t nbOfMeshes=meshes.size();
7800   int offset=0;
7801   const int *o2nPtr=o2n->getConstPointer();
7802   for(std::size_t i=0;i<nbOfMeshes;i++)
7803     {
7804       DataArrayInt *tmp=DataArrayInt::New();
7805       int curNbOfCells=meshes[i]->getNumberOfCells();
7806       tmp->alloc(curNbOfCells,1);
7807       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7808       offset+=curNbOfCells;
7809       tmp->setName(meshes[i]->getName());
7810       corr[i]=tmp;
7811     }
7812   return ret.retn();
7813 }
7814
7815 /*!
7816  * Makes all given meshes share the nodal connectivity array. The common connectivity
7817  * array is created by concatenating the connectivity arrays of all given meshes. All
7818  * the given meshes must be of the same space dimension but dimension of cells **can
7819  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7820  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7821  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7822  *  \param [in,out] meshes - a vector of meshes to update.
7823  *  \throw If any of \a meshes is NULL.
7824  *  \throw If the coordinates array is not set in any of \a meshes.
7825  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7826  *  \throw If \a meshes are of different space dimension.
7827  */
7828 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7829 {
7830   std::size_t sz=meshes.size();
7831   if(sz==0 || sz==1)
7832     return;
7833   std::vector< const DataArrayDouble * > coords(meshes.size());
7834   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7835   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7836     {
7837       if((*it))
7838         {
7839           (*it)->checkConnectivityFullyDefined();
7840           const DataArrayDouble *coo=(*it)->getCoords();
7841           if(coo)
7842             *it2=coo;
7843           else
7844             {
7845               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7846               oss << " has no coordinate array defined !";
7847               throw INTERP_KERNEL::Exception(oss.str().c_str());
7848             }
7849         }
7850       else
7851         {
7852           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7853           oss << " is null !";
7854           throw INTERP_KERNEL::Exception(oss.str().c_str());
7855         }
7856     }
7857   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7858   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7859   int offset=(*it)->getNumberOfNodes();
7860   (*it++)->setCoords(res);
7861   for(;it!=meshes.end();it++)
7862     {
7863       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7864       (*it)->setCoords(res);
7865       (*it)->shiftNodeNumbersInConn(offset);
7866       offset+=oldNumberOfNodes;
7867     }
7868 }
7869
7870 /*!
7871  * Merges nodes coincident with a given precision within all given meshes that share
7872  * the nodal connectivity array. The given meshes **can be of different** mesh
7873  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7874  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7875  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7876  *  \param [in,out] meshes - a vector of meshes to update.
7877  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7878  *  \throw If any of \a meshes is NULL.
7879  *  \throw If the \a meshes do not share the same node coordinates array.
7880  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7881  */
7882 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7883 {
7884   if(meshes.empty())
7885     return ;
7886   std::set<const DataArrayDouble *> s;
7887   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7888     {
7889       if(*it)
7890         s.insert((*it)->getCoords());
7891       else
7892         {
7893           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 !";
7894           throw INTERP_KERNEL::Exception(oss.str().c_str());
7895         }
7896     }
7897   if(s.size()!=1)
7898     {
7899       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 !";
7900       throw INTERP_KERNEL::Exception(oss.str().c_str());
7901     }
7902   const DataArrayDouble *coo=*(s.begin());
7903   if(!coo)
7904     return;
7905   //
7906   DataArrayInt *comm,*commI;
7907   coo->findCommonTuples(eps,-1,comm,commI);
7908   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7909   int oldNbOfNodes=coo->getNumberOfTuples();
7910   int newNbOfNodes;
7911   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7912   if(oldNbOfNodes==newNbOfNodes)
7913     return ;
7914   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7915   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7916     {
7917       (*it)->renumberNodesInConn(o2n->getConstPointer());
7918       (*it)->setCoords(newCoords);
7919     } 
7920 }
7921
7922 /*!
7923  * 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.
7924  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7925  * \param isQuad specifies the policy of connectivity.
7926  * @ret in/out parameter in which the result will be append
7927  */
7928 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7929 {
7930   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7931   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7932   ret.push_back(cm.getExtrudedType());
7933   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7934   switch(flatType)
7935     {
7936     case INTERP_KERNEL::NORM_POINT1:
7937       {
7938         ret.push_back(connBg[1]);
7939         ret.push_back(connBg[1]+nbOfNodesPerLev);
7940         break;
7941       }
7942     case INTERP_KERNEL::NORM_SEG2:
7943       {
7944         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7945         ret.insert(ret.end(),conn,conn+4);
7946         break;
7947       }
7948     case INTERP_KERNEL::NORM_SEG3:
7949       {
7950         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7951         ret.insert(ret.end(),conn,conn+8);
7952         break;
7953       }
7954     case INTERP_KERNEL::NORM_QUAD4:
7955       {
7956         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7957         ret.insert(ret.end(),conn,conn+8);
7958         break;
7959       }
7960     case INTERP_KERNEL::NORM_TRI3:
7961       {
7962         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7963         ret.insert(ret.end(),conn,conn+6);
7964         break;
7965       }
7966     case INTERP_KERNEL::NORM_TRI6:
7967       {
7968         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,
7969                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7970         ret.insert(ret.end(),conn,conn+15);
7971         break;
7972       }
7973     case INTERP_KERNEL::NORM_QUAD8:
7974       {
7975         int conn[20]={
7976           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7977           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7978           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7979         };
7980         ret.insert(ret.end(),conn,conn+20);
7981         break;
7982       }
7983     case INTERP_KERNEL::NORM_POLYGON:
7984       {
7985         std::back_insert_iterator< std::vector<int> > ii(ret);
7986         std::copy(connBg+1,connEnd,ii);
7987         *ii++=-1;
7988         std::reverse_iterator<const int *> rConnBg(connEnd);
7989         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7990         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7991         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7992         for(std::size_t i=0;i<nbOfRadFaces;i++)
7993           {
7994             *ii++=-1;
7995             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7996             std::copy(conn,conn+4,ii);
7997           }
7998         break;
7999       }
8000     default:
8001       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8002     }
8003 }
8004
8005 /*!
8006  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8007  */
8008 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8009 {
8010   std::size_t i, ip1;
8011   double v[3]={0.,0.,0.};
8012   std::size_t sz=std::distance(begin,end);
8013   if(isQuadratic)
8014     sz/=2;
8015   for(i=0;i<sz;i++)
8016     {
8017       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];
8018       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8019       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8020     }
8021   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8022
8023   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8024   // SEG3 forming a circle):
8025   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8026     {
8027       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8028       for(std::size_t j=0;j<sz;j++)
8029         {
8030           if (j%2)  // current point i is quadratic, next point i+1 is standard
8031             {
8032               i = sz+j;
8033               ip1 = (j+1)%sz; // ip1 = "i+1"
8034             }
8035           else      // current point i is standard, next point i+1 is quadratic
8036             {
8037               i = j;
8038               ip1 = j+sz;
8039             }
8040           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8041           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8042           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8043         }
8044       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8045     }
8046   return (ret>0.);
8047 }
8048
8049 /*!
8050  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8051  */
8052 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8053 {
8054   std::vector<std::pair<int,int> > edges;
8055   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8056   const int *bgFace=begin;
8057   for(std::size_t i=0;i<nbOfFaces;i++)
8058     {
8059       const int *endFace=std::find(bgFace+1,end,-1);
8060       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8061       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8062         {
8063           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8064           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8065             return false;
8066           edges.push_back(p1);
8067         }
8068       bgFace=endFace+1;
8069     }
8070   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8071 }
8072
8073 /*!
8074  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8075  */
8076 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8077 {
8078   double vec0[3],vec1[3];
8079   std::size_t sz=std::distance(begin,end);
8080   if(sz%2!=0)
8081     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8082   int nbOfNodes=(int)sz/2;
8083   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8084   const double *pt0=coords+3*begin[0];
8085   const double *pt1=coords+3*begin[nbOfNodes];
8086   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8087   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8088 }
8089
8090 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8091 {
8092   std::size_t sz=std::distance(begin,end);
8093   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8094   std::size_t nbOfNodes(sz/2);
8095   std::copy(begin,end,(int *)tmp);
8096   for(std::size_t j=1;j<nbOfNodes;j++)
8097     {
8098       begin[j]=tmp[nbOfNodes-j];
8099       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8100     }
8101 }
8102
8103 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8104 {
8105   std::size_t sz=std::distance(begin,end);
8106   if(sz!=4)
8107     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8108   double vec0[3],vec1[3];
8109   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8110   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]; 
8111   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;
8112 }
8113
8114 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8115 {
8116   std::size_t sz=std::distance(begin,end);
8117   if(sz!=5)
8118     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8119   double vec0[3];
8120   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8121   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8122   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8123 }
8124
8125 /*!
8126  * 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 ) 
8127  * 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
8128  * a 2D space.
8129  *
8130  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8131  * \param [in] coords the coordinates with nb of components exactly equal to 3
8132  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8133  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8134  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8135  */
8136 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8137 {
8138   int nbFaces=std::count(begin+1,end,-1)+1;
8139   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8140   double *vPtr=v->getPointer();
8141   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8142   double *pPtr=p->getPointer();
8143   const int *stFaceConn=begin+1;
8144   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8145     {
8146       const int *endFaceConn=std::find(stFaceConn,end,-1);
8147       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8148       stFaceConn=endFaceConn+1;
8149     }
8150   pPtr=p->getPointer(); vPtr=v->getPointer();
8151   DataArrayInt *comm1=0,*commI1=0;
8152   v->findCommonTuples(eps,-1,comm1,commI1);
8153   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8154   const int *comm1Ptr=comm1->getConstPointer();
8155   const int *commI1Ptr=commI1->getConstPointer();
8156   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8157   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8158   //
8159   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8160   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8161   mm->finishInsertingCells();
8162   //
8163   for(int i=0;i<nbOfGrps1;i++)
8164     {
8165       int vecId=comm1Ptr[commI1Ptr[i]];
8166       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8167       DataArrayInt *comm2=0,*commI2=0;
8168       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8169       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8170       const int *comm2Ptr=comm2->getConstPointer();
8171       const int *commI2Ptr=commI2->getConstPointer();
8172       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8173       for(int j=0;j<nbOfGrps2;j++)
8174         {
8175           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8176             {
8177               res->insertAtTheEnd(begin,end);
8178               res->pushBackSilent(-1);
8179             }
8180           else
8181             {
8182               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8183               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8184               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8185               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8186               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8187               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8188               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8189               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8190               const int *idsNodePtr=idsNode->getConstPointer();
8191               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];
8192               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8193               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8194               if(std::abs(norm)>eps)
8195                 {
8196                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8197                   mm3->rotate(center,vec,angle);
8198                 }
8199               mm3->changeSpaceDimension(2);
8200               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8201               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8202               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8203               int nbOfCells=mm4->getNumberOfCells();
8204               for(int k=0;k<nbOfCells;k++)
8205                 {
8206                   int l=0;
8207                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8208                     res->pushBackSilent(idsNodePtr[*work]);
8209                   res->pushBackSilent(-1);
8210                 }
8211             }
8212         }
8213     }
8214   res->popBackSilent();
8215 }
8216
8217 /*!
8218  * 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
8219  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8220  * 
8221  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8222  * \param [in] coords coordinates expected to have 3 components.
8223  * \param [in] begin start of the nodal connectivity of the face.
8224  * \param [in] end end of the nodal connectivity (excluded) of the face.
8225  * \param [out] v the normalized vector of size 3
8226  * \param [out] p the pos of plane
8227  */
8228 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8229 {
8230   std::size_t nbPoints=std::distance(begin,end);
8231   if(nbPoints<3)
8232     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8233   double vec[3]={0.,0.,0.};
8234   std::size_t j=0;
8235   bool refFound=false;
8236   for(;j<nbPoints-1 && !refFound;j++)
8237     {
8238       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8239       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8240       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8241       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8242       if(norm>eps)
8243         {
8244           refFound=true;
8245           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8246         }
8247     }
8248   for(std::size_t i=j;i<nbPoints-1;i++)
8249     {
8250       double curVec[3];
8251       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8252       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8253       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8254       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8255       if(norm<eps)
8256         continue;
8257       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8258       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];
8259       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8260       if(norm>eps)
8261         {
8262           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8263           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8264           return ;
8265         }
8266     }
8267   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8268 }
8269
8270 /*!
8271  * This method tries to obtain a well oriented polyhedron.
8272  * If the algorithm fails, an exception will be thrown.
8273  */
8274 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8275 {
8276   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8277   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8278   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8279   isPerm[0]=true;
8280   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8281   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8282   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8283   //
8284   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8285     {
8286       bgFace=begin;
8287       std::size_t smthChanged=0;
8288       for(std::size_t i=0;i<nbOfFaces;i++)
8289         {
8290           endFace=std::find(bgFace+1,end,-1);
8291           nbOfEdgesInFace=std::distance(bgFace,endFace);
8292           if(!isPerm[i])
8293             {
8294               bool b;
8295               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8296                 {
8297                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8298                   std::pair<int,int> p2(p1.second,p1.first);
8299                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8300                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8301                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8302                 }
8303               if(isPerm[i])
8304                 { 
8305                   if(!b)
8306                     std::reverse(bgFace+1,endFace);
8307                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8308                     {
8309                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8310                       std::pair<int,int> p2(p1.second,p1.first);
8311                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8312                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8313                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8314                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8315                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8316                       if(it!=edgesOK.end())
8317                         {
8318                           edgesOK.erase(it);
8319                           edgesFinished.push_back(p1);
8320                         }
8321                       else
8322                         edgesOK.push_back(p1);
8323                     }
8324                 }
8325             }
8326           bgFace=endFace+1;
8327         }
8328       if(smthChanged==0)
8329         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8330     }
8331   if(!edgesOK.empty())
8332     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8333   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8334     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8335       bgFace=begin;
8336       for(std::size_t i=0;i<nbOfFaces;i++)
8337         {
8338           endFace=std::find(bgFace+1,end,-1);
8339           std::reverse(bgFace+1,endFace);
8340           bgFace=endFace+1;
8341         }
8342     }
8343 }
8344
8345 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8346 {
8347   int nbOfNodesExpected(skin->getNumberOfNodes());
8348   const int *n2oPtr(n2o->getConstPointer());
8349   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8350   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8351   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8352   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8353   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8354   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8355   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8356   if(nbOfNodesExpected<1)
8357     return ret.retn();
8358   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8359   *work++=n2oPtr[prevNode];
8360   for(int i=1;i<nbOfNodesExpected;i++)
8361     {
8362       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8363         {
8364           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8365           conn.erase(prevNode);
8366           if(conn.size()==1)
8367             {
8368               int curNode(*(conn.begin()));
8369               *work++=n2oPtr[curNode];
8370               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8371               shar.erase(prevCell);
8372               if(shar.size()==1)
8373                 {
8374                   prevCell=*(shar.begin());
8375                   prevNode=curNode;
8376                 }
8377               else
8378                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8379             }
8380           else
8381             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8382         }
8383       else
8384         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8385     }
8386   return ret.retn();
8387 }
8388
8389 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8390 {
8391   int nbOfNodesExpected(skin->getNumberOfNodes());
8392   int nbOfTurn(nbOfNodesExpected/2);
8393   const int *n2oPtr(n2o->getConstPointer());
8394   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8395   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8396   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8397   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8398   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8400   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8401   if(nbOfNodesExpected<1)
8402     return ret.retn();
8403   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8404   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8405   for(int i=1;i<nbOfTurn;i++)
8406     {
8407       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8408         {
8409           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8410           conn.erase(prevNode);
8411           if(conn.size()==1)
8412             {
8413               int curNode(*(conn.begin()));
8414               *work=n2oPtr[curNode];
8415               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8416               shar.erase(prevCell);
8417               if(shar.size()==1)
8418                 {
8419                   int curCell(*(shar.begin()));
8420                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8421                   prevCell=curCell;
8422                   prevNode=curNode;
8423                   work++;
8424                 }
8425               else
8426                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8427             }
8428           else
8429             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8430         }
8431       else
8432         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8433     }
8434   return ret.retn();
8435 }
8436
8437 /*!
8438  * This method makes the assumption spacedimension == meshdimension == 2.
8439  * This method works only for linear cells.
8440  * 
8441  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8442  */
8443 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8444 {
8445   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8446     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8447   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8448   int oldNbOfNodes(skin->getNumberOfNodes());
8449   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8450   int nbOfNodesExpected(skin->getNumberOfNodes());
8451   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8452   int nbCells(skin->getNumberOfCells());
8453   if(nbCells==nbOfNodesExpected)
8454     return buildUnionOf2DMeshLinear(skin,n2o);
8455   else if(2*nbCells==nbOfNodesExpected)
8456     return buildUnionOf2DMeshQuadratic(skin,n2o);
8457   else
8458     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8459 }
8460
8461 /*!
8462  * This method makes the assumption spacedimension == meshdimension == 3.
8463  * This method works only for linear cells.
8464  * 
8465  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8466  */
8467 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8468 {
8469   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8470     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8471   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8472   const int *conn=m->getNodalConnectivity()->getConstPointer();
8473   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8474   int nbOfCells=m->getNumberOfCells();
8475   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8476   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8477   if(nbOfCells<1)
8478     return ret.retn();
8479   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8480   for(int i=1;i<nbOfCells;i++)
8481     {
8482       *work++=-1;
8483       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8484     }
8485   return ret.retn();
8486 }
8487
8488 /*!
8489  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8490  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8491  */
8492 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8493 {
8494   double *w=zipFrmt;
8495   if(spaceDim==3)
8496     for(int i=0;i<nbOfNodesInCell;i++)
8497       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8498   else if(spaceDim==2)
8499     {
8500       for(int i=0;i<nbOfNodesInCell;i++)
8501         {
8502           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8503           *w++=0.;
8504         }
8505     }
8506   else
8507     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8508 }
8509
8510 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8511 {
8512   int nbOfCells=getNumberOfCells();
8513   if(nbOfCells<=0)
8514     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8515   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};
8516   ofs << "  <" << getVTKDataSetType() << ">\n";
8517   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8518   ofs << "      <PointData>\n" << pointData << std::endl;
8519   ofs << "      </PointData>\n";
8520   ofs << "      <CellData>\n" << cellData << std::endl;
8521   ofs << "      </CellData>\n";
8522   ofs << "      <Points>\n";
8523   if(getSpaceDimension()==3)
8524     _coords->writeVTK(ofs,8,"Points",byteData);
8525   else
8526     {
8527       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8528       coo->writeVTK(ofs,8,"Points",byteData);
8529     }
8530   ofs << "      </Points>\n";
8531   ofs << "      <Cells>\n";
8532   const int *cPtr=_nodal_connec->getConstPointer();
8533   const int *cIPtr=_nodal_connec_index->getConstPointer();
8534   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8535   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8536   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8537   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8538   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8539   int szFaceOffsets=0,szConn=0;
8540   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8541     {
8542       *w2=cPtr[cIPtr[i]];
8543       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8544         {
8545           *w1=-1;
8546           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8547           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8548         }
8549       else
8550         {
8551           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8552           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8553           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8554           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8555           w4=std::copy(c.begin(),c.end(),w4);
8556         }
8557     }
8558   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8559   types->writeVTK(ofs,8,"UInt8","types",byteData);
8560   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8561   if(szFaceOffsets!=0)
8562     {//presence of Polyhedra
8563       connectivity->reAlloc(szConn);
8564       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8565       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8566       w1=faces->getPointer();
8567       for(int i=0;i<nbOfCells;i++)
8568         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8569           {
8570             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8571             *w1++=nbFaces;
8572             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8573             for(int j=0;j<nbFaces;j++)
8574               {
8575                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8576                 *w1++=(int)std::distance(w6,w5);
8577                 w1=std::copy(w6,w5,w1);
8578                 w6=w5+1;
8579               }
8580           }
8581       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8582     }
8583   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8584   ofs << "      </Cells>\n";
8585   ofs << "    </Piece>\n";
8586   ofs << "  </" << getVTKDataSetType() << ">\n";
8587 }
8588
8589 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8590 {
8591   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8592   if(_mesh_dim==-2)
8593     { stream << " Not set !"; return ; }
8594   stream << " Mesh dimension : " << _mesh_dim << ".";
8595   if(_mesh_dim==-1)
8596     return ;
8597   if(!_coords)
8598     { stream << " No coordinates set !"; return ; }
8599   if(!_coords->isAllocated())
8600     { stream << " Coordinates set but not allocated !"; return ; }
8601   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8602   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8603   if(!_nodal_connec_index)
8604     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8605   if(!_nodal_connec_index->isAllocated())
8606     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8607   int lgth=_nodal_connec_index->getNumberOfTuples();
8608   int cpt=_nodal_connec_index->getNumberOfComponents();
8609   if(cpt!=1 || lgth<1)
8610     return ;
8611   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8612 }
8613
8614 std::string MEDCouplingUMesh::getVTKDataSetType() const
8615 {
8616   return std::string("UnstructuredGrid");
8617 }
8618
8619 /*!
8620  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8621  * returns a result mesh constituted by polygons.
8622  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8623  * all nodes from m2.
8624  * The meshes should be in 2D space. In
8625  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8626  * meshes.
8627  *  \param [in] m1 - the first input mesh which is a partitioned object.
8628  *  \param [in] m2 - the second input mesh which is a partition tool.
8629  *  \param [in] eps - precision used to detect coincident mesh entities.
8630  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8631  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8632  *         this array using decrRef() as it is no more needed.
8633  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8634  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8635  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8636  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8637  *         it is no more needed.  
8638  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8639  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8640  *         is no more needed.  
8641  *  \throw If the coordinates array is not set in any of the meshes.
8642  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8643  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8644  */
8645 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8646                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8647 {
8648   m1->checkFullyDefined();
8649   m2->checkFullyDefined();
8650   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8651     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8652
8653   // Step 1: compute all edge intersections (new nodes)
8654   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8655   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8656   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8657   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8658   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8659   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8660   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8661                                       m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8662                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8663   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8664   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8665   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8666
8667   // Step 2: re-order newly created nodes according to the ordering found in m2
8668   std::vector< std::vector<int> > intersectEdge2;
8669   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8670   subDiv2.clear(); dd5=0; dd6=0;
8671
8672   // Step 3:
8673   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8674   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8675   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8676                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8677
8678   // Step 4: Prepare final result:
8679   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8680   addCooDa->alloc((int)(addCoo.size())/2,2);
8681   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8682   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8683   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8684   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8685   std::vector<const DataArrayDouble *> coordss(4);
8686   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8687   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8688   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8689   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8690   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8691   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8692   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8693   ret->setConnectivity(conn,connI,true);
8694   ret->setCoords(coo);
8695   cellNb1=c1.retn(); cellNb2=c2.retn();
8696   return ret.retn();
8697 }
8698
8699
8700 /**
8701  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
8702  * (newly created) nodes corresponding to the edge intersections.
8703  * Output params:
8704  * @param[out] cr, crI connectivity of the resulting mesh
8705  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
8706  * TODO: describe input parameters
8707  */
8708 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8709                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8710                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8711                                                          const std::vector<double>& addCoords,
8712                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8713 {
8714   static const int SPACEDIM=2;
8715   const double *coo1=m1->getCoords()->getConstPointer();
8716   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8717   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8718   int offset1=m1->getNumberOfNodes();
8719   const double *coo2=m2->getCoords()->getConstPointer();
8720   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8721   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8722   int offset2=offset1+m2->getNumberOfNodes();
8723   int offset3=offset2+((int)addCoords.size())/2;
8724   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8725   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8726   // Here a BBTree on 2D-cells, not on segments:
8727   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8728   int ncell1=m1->getNumberOfCells();
8729   crI.push_back(0);
8730   for(int i=0;i<ncell1;i++)
8731     {
8732       std::vector<int> candidates2;
8733       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8734       std::map<INTERP_KERNEL::Node *,int> mapp;
8735       std::map<int,INTERP_KERNEL::Node *> mappRev;
8736       INTERP_KERNEL::QuadraticPolygon pol1;
8737       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8738       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8739       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
8740       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8741       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
8742       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8743                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8744       //
8745       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
8746       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8747       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8748       for(it1.first();!it1.finished();it1.next())
8749         edges1.insert(it1.current()->getPtr());
8750       //
8751       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
8752       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8753       int ii=0;
8754       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8755         {
8756           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8757           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8758           // Complete mapping with elements coming from the current cell it2 in mesh2:
8759           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8760           // pol2 is the new QP in the final merged result.
8761           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8762                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
8763         }
8764       ii=0;
8765       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8766         {
8767           pol1.initLocationsWithOther(pol2s[ii]);
8768           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8769           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8770           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8771         }
8772       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
8773       // by m2 but that we still want to keep in the final result.
8774       if(!edges1.empty())
8775         {
8776           try
8777             {
8778               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8779             }
8780           catch(INTERP_KERNEL::Exception& e)
8781             {
8782               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();
8783               throw INTERP_KERNEL::Exception(oss.str().c_str());
8784             }
8785         }
8786       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8787         (*it).second->decrRef();
8788     }
8789 }
8790
8791 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8792 {
8793   std::map<INTERP_KERNEL::Node *,int>::const_iterator it(m.find(n));
8794   if(it==m.end())
8795     throw INTERP_KERNEL::Exception("Internal error in remapping !");
8796   int v((*it).second);
8797   if(v==forbVal0 || v==forbVal1)
8798     return ;
8799   if(std::find(isect.begin(),isect.end(),v)==isect.end())
8800     isect.push_back(v);
8801 }
8802
8803 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8804 {
8805   int sz(c.size());
8806   if(sz<=1)
8807     return false;
8808   bool presenceOfOn(false);
8809   for(int i=0;i<sz;i++)
8810     {
8811       INTERP_KERNEL::ElementaryEdge *e(c[i]);
8812       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
8813         continue ;
8814       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
8815       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
8816     }
8817   return presenceOfOn;
8818 }
8819
8820 /**
8821  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg and in \a subNodesInSegI using index storage mode.
8822  * To do the work this method can optionnaly needs information about middle of subedges for quadratic cases if a minimal creation of new nodes is wanted.
8823  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add nodes if a SEG3 is split without information of middle.
8824  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
8825  *
8826  * \return int - the number of new nodes created (in most of cases 0).
8827  * 
8828  * \throw If \a this is not coherent.
8829  * \throw If \a this has not spaceDim equal to 2.
8830  * \throw If \a this has not meshDim equal to 2.
8831  * \throw If some subcells needed to be split are orphan.
8832  * \sa MEDCouplingUMesh::conformize2D
8833  */
8834 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
8835 {
8836   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
8837     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
8838   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
8839   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
8840     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
8841   if(midOpt==0 && midOptI==0)
8842     {
8843       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
8844       return 0;
8845     }
8846   else if(midOpt!=0 && midOptI!=0)
8847     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
8848   else
8849     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
8850 }
8851
8852 /*!
8853  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
8854  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
8855  * This method performs a conformization of \b this. So if a edge in \a this can be split into entire edges in \a this this method
8856  * will suppress such edges to use sub edges in \a this. So this method does not add nodes in \a this if merged edges have same nature each other (Linear,Quadratic).
8857  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
8858  * The modified cells if any are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the 
8859  *
8860  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
8861  * This method expects that all nodes in \a this are not closer than \a eps.
8862  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
8863  * 
8864  * \param [in] eps the relative error to detect merged edges.
8865  * \return DataArrayInt  * - The list of cellIds in \a this that have been subdivided. If empty, nothing changed in \a this (as if it were a const method). The array is a newly allocated array
8866  *                           that the user is expected to deal with.
8867  *
8868  * \throw If \a this is not coherent.
8869  * \throw If \a this has not spaceDim equal to 2.
8870  * \throw If \a this has not meshDim equal to 2.
8871  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
8872  */
8873 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
8874 {
8875   static const int SPACEDIM=2;
8876   checkCoherency();
8877   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
8878     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
8879   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
8880   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
8881   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
8882   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
8883   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
8884   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
8885   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
8886   std::vector<double> addCoo;
8887   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
8888   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8889   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8890   for(int i=0;i<nDescCell;i++)
8891     {
8892       std::vector<int> candidates;
8893       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
8894       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8895         if(*it>i)
8896           {
8897             std::map<INTERP_KERNEL::Node *,int> m;
8898             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
8899               *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
8900             INTERP_KERNEL::MergePoints merge;
8901             INTERP_KERNEL::QuadraticPolygon c1,c2;
8902             e1->intersectWith(e2,merge,c1,c2);
8903             e1->decrRef(); e2->decrRef();
8904             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
8905               overlapEdge[i].push_back(*it);
8906             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
8907               overlapEdge[*it].push_back(i);
8908             for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
8909               (*it2).first->decrRef();
8910           }
8911     }
8912   // splitting done. sort intersect point in intersectEdge.
8913   std::vector< std::vector<int> > middle(nDescCell);
8914   int nbOf2DCellsToBeSplit(0);
8915   bool middleNeedsToBeUsed(false);
8916   std::vector<bool> cells2DToTreat(nDescCell,false);
8917   for(int i=0;i<nDescCell;i++)
8918     {
8919       std::vector<int>& isect(intersectEdge[i]);
8920       int sz((int)isect.size());
8921       if(sz>1)
8922         {
8923           std::map<INTERP_KERNEL::Node *,int> m;
8924           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
8925           e->sortSubNodesAbs(coords,isect);
8926           e->decrRef();
8927           for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
8928             (*it2).first->decrRef();
8929         }
8930       if(sz!=0)
8931         {
8932           int idx0(rdi[i]),idx1(rdi[i+1]);
8933           if(idx1-idx0!=1)
8934             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
8935           if(!cells2DToTreat[rd[idx0]])
8936             {
8937               cells2DToTreat[rd[idx0]]=true;
8938               nbOf2DCellsToBeSplit++;
8939             }
8940           // try to reuse at most eventual 'middle' of SEG3
8941           std::vector<int>& mid(middle[i]);
8942           mid.resize(sz+1,-1);
8943           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
8944             {
8945               middleNeedsToBeUsed=true;
8946               const std::vector<int>& candidates(overlapEdge[i]);
8947               std::vector<int> trueCandidates;
8948               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
8949                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
8950                   trueCandidates.push_back(*itc);
8951               int stNode(c[ci[i]+1]),endNode(isect[0]);
8952               for(int j=0;j<sz+1;j++)
8953                 {
8954                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
8955                     {
8956                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
8957                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
8958                         { mid[j]=*itc; break; }
8959                     }
8960                   stNode=endNode;
8961                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
8962                 }
8963             }
8964         }
8965     }
8966   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
8967   if(nbOf2DCellsToBeSplit==0)
8968     return ret.retn();
8969   //
8970   int *retPtr(ret->getPointer());
8971   for(int i=0;i<nCell;i++)
8972     if(cells2DToTreat[i])
8973       *retPtr++=i;
8974   //
8975   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
8976   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
8977   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
8978   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
8979   if(middleNeedsToBeUsed)
8980     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
8981   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
8982   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
8983   setCoords(modif->getCoords());//if nbOfNodesCreated==0 modif and this have the same coordinates pointer so this line has no effect. But for quadratic cases this line is important.
8984   setPartOfMySelf(ret->begin(),ret->end(),*modif);
8985   {
8986     bool areNodesMerged; int newNbOfNodes;
8987     if(nbOfNodesCreated!=0)
8988       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
8989   }
8990   return ret.retn();
8991 }
8992
8993 /*!
8994  * This non const method works on 2D mesh. This method scans every cell in \a this and look if each edge constituting this cell is not mergeable with neighbors edges of that cell.
8995  * If yes, the cell is "repaired" to minimize at most its number of edges. So this method do not change the overall shape of cells in \a this (with eps precision).
8996  * This method do not take care of shared edges between cells, so this method can lead to a non conform mesh (\a this). If a conform mesh is required you're expected
8997  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
8998  * This method works on any 2D geometric types of cell (even static one). If a cell is touched its type becomes dynamic automaticaly. For 2D "repaired" quadratic cells
8999  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
9000  *
9001  * If the returned array is empty it means that nothing has changed in \a this (as if it were a const method). If the array is not empty the connectivity of \a this is modified
9002  * using new instance, idem for coordinates.
9003  *
9004  * If \a this is constituted by only linear 2D cells, this method is close to the computation of the convex hull of each cells in \a this.
9005  * 
9006  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
9007  *
9008  * \throw If \a this is not coherent.
9009  * \throw If \a this has not spaceDim equal to 2.
9010  * \throw If \a this has not meshDim equal to 2.
9011  * 
9012  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
9013  */
9014 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
9015 {
9016   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
9017   checkCoherency();
9018   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9019     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9020   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9021   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9022   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
9023   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
9024   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
9025   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
9026   const double *coords(_coords->begin());
9027   int *newciptr(newci->getPointer());
9028   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
9029     {
9030       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
9031         ret->pushBackSilent(i);
9032       newciptr[1]=newc->getNumberOfTuples();
9033     }
9034   //
9035   if(ret->empty())
9036     return ret.retn();
9037   if(!appendedCoords->empty())
9038     {
9039       appendedCoords->rearrange(2);
9040       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
9041       //non const part
9042       setCoords(newCoords);
9043     }
9044   //non const part
9045   setConnectivity(newc,newci,true);
9046   return ret.retn();
9047 }
9048
9049 /*!
9050  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
9051  * It builds the descending connectivity of the two meshes, and then using a binary tree
9052  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
9053  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
9054  */
9055 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
9056                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
9057                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
9058                                                    std::vector<double>& addCoo,
9059                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
9060                                                    throw(INTERP_KERNEL::Exception)
9061 {
9062   static const int SPACEDIM=2;
9063   // Build desc connectivity
9064   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
9065   desc2=DataArrayInt::New();
9066   descIndx2=DataArrayInt::New();
9067   revDesc2=DataArrayInt::New();
9068   revDescIndx2=DataArrayInt::New();
9069   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9070   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
9071   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
9072   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
9073   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
9074   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
9075   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
9076
9077   // Build BB tree of all edges in the tool mesh (second mesh)
9078   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
9079   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9080   int nDescCell1=m1Desc->getNumberOfCells();
9081   int nDescCell2=m2Desc->getNumberOfCells();
9082   intersectEdge1.resize(nDescCell1);
9083   colinear2.resize(nDescCell2);
9084   subDiv2.resize(nDescCell2);
9085   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
9086
9087   std::vector<int> candidates1(1);
9088   int offset1=m1->getNumberOfNodes();
9089   int offset2=offset1+m2->getNumberOfNodes();
9090   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
9091     {
9092       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
9093       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9094       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
9095         {
9096           std::map<INTERP_KERNEL::Node *,int> map1,map2;
9097           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
9098           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
9099           candidates1[0]=i;
9100           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
9101           // 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
9102           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
9103           std::set<INTERP_KERNEL::Node *> nodes;
9104           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
9105           std::size_t szz(nodes.size());
9106           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
9107           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
9108           for(std::size_t iii=0;iii<szz;iii++,itt++)
9109             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
9110           // end of protection
9111           // Performs egde cutting:
9112           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
9113           delete pol2;
9114           delete pol1;
9115         }
9116       else
9117         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
9118     }
9119   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
9120   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
9121 }
9122
9123 /*!
9124  * This method performs the 2nd step of Partition of 2D mesh.
9125  * This method has 4 inputs :
9126  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
9127  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
9128  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
9129  * 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'
9130  * Nodes end up lying consecutively on a cutted edge.
9131  * \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.
9132  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
9133  * \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.
9134  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
9135  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
9136  */
9137 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9138       const std::vector<double>& addCoo,
9139       const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
9140 {
9141   int offset1=m1->getNumberOfNodes();
9142   int ncell=m2->getNumberOfCells();
9143   const int *c=m2->getNodalConnectivity()->getConstPointer();
9144   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
9145   const double *coo=m2->getCoords()->getConstPointer();
9146   const double *cooBis=m1->getCoords()->getConstPointer();
9147   int offset2=offset1+m2->getNumberOfNodes();
9148   intersectEdge.resize(ncell);
9149   for(int i=0;i<ncell;i++,cI++)
9150     {
9151       const std::vector<int>& divs=subDiv[i];
9152       int nnode=cI[1]-cI[0]-1;
9153       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
9154       std::map<INTERP_KERNEL::Node *, int> mapp22;
9155       for(int j=0;j<nnode;j++)
9156         {
9157           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
9158           int nnid=c[(*cI)+j+1];
9159           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
9160           mapp22[nn]=nnid+offset1;
9161         }
9162       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
9163       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
9164         ((*it).second.first)->decrRef();
9165       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
9166       std::map<INTERP_KERNEL::Node *,int> mapp3;
9167       for(std::size_t j=0;j<divs.size();j++)
9168         {
9169           int id=divs[j];
9170           INTERP_KERNEL::Node *tmp=0;
9171           if(id<offset1)
9172             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
9173           else if(id<offset2)
9174             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
9175           else
9176             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
9177           addNodes[j]=tmp;
9178           mapp3[tmp]=id;
9179         }
9180       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
9181       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
9182         (*it)->decrRef();
9183       e->decrRef();
9184     }
9185 }
9186
9187 /*!
9188  * 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).
9189  * 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
9190  * with a plane. The result will be put in 'cut3DSuf' out parameter.
9191  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
9192  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
9193  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
9194  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
9195  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
9196  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
9197  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
9198  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
9199  * \param [out] cut3DSuf input/output param.
9200  */
9201 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
9202                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
9203                                                    const int *desc, const int *descIndx, 
9204                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
9205 {
9206   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
9207   int nbOf3DSurfCell=(int)cut3DSurf.size();
9208   for(int i=0;i<nbOf3DSurfCell;i++)
9209     {
9210       std::vector<int> res;
9211       int offset=descIndx[i];
9212       int nbOfSeg=descIndx[i+1]-offset;
9213       for(int j=0;j<nbOfSeg;j++)
9214         {
9215           int edgeId=desc[offset+j];
9216           int status=cut3DCurve[edgeId];
9217           if(status!=-2)
9218             {
9219               if(status>-1)
9220                 res.push_back(status);
9221               else
9222                 {
9223                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
9224                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
9225                 }
9226             }
9227         }
9228       switch(res.size())
9229         {
9230         case 2:
9231           {
9232             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9233             break;
9234           }
9235         case 1:
9236         case 0:
9237           {
9238             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
9239             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
9240             if(res.size()==2)
9241               {
9242                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9243               }
9244             else
9245               {
9246                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
9247               }
9248             break;
9249           }
9250         default:
9251           {// case when plane is on a multi colinear edge of a polyhedron
9252             if((int)res.size()==2*nbOfSeg)
9253               {
9254                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
9255               }
9256             else
9257               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
9258           }
9259         }
9260     }
9261 }
9262
9263 /*!
9264  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
9265  * 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).
9266  * 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
9267  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
9268  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
9269  * \param desc is the descending connectivity 3D->3DSurf
9270  * \param descIndx is the descending connectivity index 3D->3DSurf
9271  */
9272 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
9273                                                   const int *desc, const int *descIndx,
9274                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
9275 {
9276   checkFullyDefined();
9277   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9278     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
9279   const int *nodal3D=_nodal_connec->getConstPointer();
9280   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
9281   int nbOfCells=getNumberOfCells();
9282   for(int i=0;i<nbOfCells;i++)
9283     {
9284       std::map<int, std::set<int> > m;
9285       int offset=descIndx[i];
9286       int nbOfFaces=descIndx[i+1]-offset;
9287       int start=-1;
9288       int end=-1;
9289       for(int j=0;j<nbOfFaces;j++)
9290         {
9291           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
9292           if(p.first!=-1 && p.second!=-1)
9293             {
9294               if(p.first!=-2)
9295                 {
9296                   start=p.first; end=p.second;
9297                   m[p.first].insert(p.second);
9298                   m[p.second].insert(p.first);
9299                 }
9300               else
9301                 {
9302                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
9303                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
9304                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
9305                   INTERP_KERNEL::NormalizedCellType cmsId;
9306                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
9307                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
9308                   for(unsigned k=0;k<nbOfNodesSon;k++)
9309                     {
9310                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
9311                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
9312                     }
9313                 }
9314             }
9315         }
9316       if(m.empty())
9317         continue;
9318       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
9319       int prev=end;
9320       while(end!=start)
9321         {
9322           std::map<int, std::set<int> >::const_iterator it=m.find(start);
9323           const std::set<int>& s=(*it).second;
9324           std::set<int> s2; s2.insert(prev);
9325           std::set<int> s3;
9326           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
9327           if(s3.size()==1)
9328             {
9329               int val=*s3.begin();
9330               conn.push_back(start);
9331               prev=start;
9332               start=val;
9333             }
9334           else
9335             start=end;
9336         }
9337       conn.push_back(end);
9338       if(conn.size()>3)
9339         {
9340           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
9341           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
9342           cellIds->pushBackSilent(i);
9343         }
9344     }
9345 }
9346
9347 /*!
9348  * 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
9349  * 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
9350  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
9351  * 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
9352  * 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.
9353  * 
9354  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
9355  */
9356 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
9357 {
9358   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
9359   if(sz>=4)
9360     {
9361       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
9362       if(cm.getDimension()==2)
9363         {
9364           const int *node=nodalConnBg+1;
9365           int startNode=*node++;
9366           double refX=coords[2*startNode];
9367           for(;node!=nodalConnEnd;node++)
9368             {
9369               if(coords[2*(*node)]<refX)
9370                 {
9371                   startNode=*node;
9372                   refX=coords[2*startNode];
9373                 }
9374             }
9375           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
9376           refX=1e300;
9377           double tmp1;
9378           double tmp2[2];
9379           double angle0=-M_PI/2;
9380           //
9381           int nextNode=-1;
9382           int prevNode=-1;
9383           double resRef;
9384           double angleNext=0.;
9385           while(nextNode!=startNode)
9386             {
9387               nextNode=-1;
9388               resRef=1e300;
9389               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
9390                 {
9391                   if(*node!=tmpOut.back() && *node!=prevNode)
9392                     {
9393                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
9394                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
9395                       double res;
9396                       if(angleM<=angle0)
9397                         res=angle0-angleM;
9398                       else
9399                         res=angle0-angleM+2.*M_PI;
9400                       if(res<resRef)
9401                         {
9402                           nextNode=*node;
9403                           resRef=res;
9404                           angleNext=angleM;
9405                         }
9406                     }
9407                 }
9408               if(nextNode!=startNode)
9409                 {
9410                   angle0=angleNext-M_PI;
9411                   if(angle0<-M_PI)
9412                     angle0+=2*M_PI;
9413                   prevNode=tmpOut.back();
9414                   tmpOut.push_back(nextNode);
9415                 }
9416             }
9417           std::vector<int> tmp3(2*(sz-1));
9418           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
9419           std::copy(nodalConnBg+1,nodalConnEnd,it);
9420           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
9421             {
9422               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9423               return false;
9424             }
9425           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
9426             {
9427               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9428               return false;
9429             }
9430           else
9431             {
9432               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
9433               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
9434               return true;
9435             }
9436         }
9437       else
9438         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9439     }
9440   else
9441     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9442 }
9443
9444 /*!
9445  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
9446  * 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.
9447  * 
9448  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
9449  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
9450  * \param [in,out] arr array in which the remove operation will be done.
9451  * \param [in,out] arrIndx array in the remove operation will modify
9452  * \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])
9453  * \return true if \b arr and \b arrIndx have been modified, false if not.
9454  */
9455 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
9456 {
9457   if(!arrIndx || !arr)
9458     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
9459   if(offsetForRemoval<0)
9460     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
9461   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
9462   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
9463   int *arrIPtr=arrIndx->getPointer();
9464   *arrIPtr++=0;
9465   int previousArrI=0;
9466   const int *arrPtr=arr->getConstPointer();
9467   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
9468   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
9469     {
9470       if(*arrIPtr-previousArrI>offsetForRemoval)
9471         {
9472           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
9473             {
9474               if(s.find(*work)==s.end())
9475                 arrOut.push_back(*work);
9476             }
9477         }
9478       previousArrI=*arrIPtr;
9479       *arrIPtr=(int)arrOut.size();
9480     }
9481   if(arr->getNumberOfTuples()==(int)arrOut.size())
9482     return false;
9483   arr->alloc((int)arrOut.size(),1);
9484   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
9485   return true;
9486 }
9487
9488 /*!
9489  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9490  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
9491  * The selection of extraction is done standardly in new2old format.
9492  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9493  *
9494  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9495  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9496  * \param [in] arrIn arr origin array from which the extraction will be done.
9497  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9498  * \param [out] arrOut the resulting array
9499  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9500  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
9501  */
9502 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9503                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9504 {
9505   if(!arrIn || !arrIndxIn)
9506     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
9507   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9508   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9509     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
9510   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
9511   const int *arrInPtr=arrIn->getConstPointer();
9512   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9513   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9514   if(nbOfGrps<0)
9515     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9516   int maxSizeOfArr=arrIn->getNumberOfTuples();
9517   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9518   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9519   arrIo->alloc((int)(sz+1),1);
9520   const int *idsIt=idsOfSelectBg;
9521   int *work=arrIo->getPointer();
9522   *work++=0;
9523   int lgth=0;
9524   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
9525     {
9526       if(*idsIt>=0 && *idsIt<nbOfGrps)
9527         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
9528       else
9529         {
9530           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9531           throw INTERP_KERNEL::Exception(oss.str().c_str());
9532         }
9533       if(lgth>=work[-1])
9534         *work=lgth;
9535       else
9536         {
9537           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
9538           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
9539           throw INTERP_KERNEL::Exception(oss.str().c_str());
9540         }
9541     }
9542   arro->alloc(lgth,1);
9543   work=arro->getPointer();
9544   idsIt=idsOfSelectBg;
9545   for(std::size_t i=0;i<sz;i++,idsIt++)
9546     {
9547       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
9548         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
9549       else
9550         {
9551           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
9552           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9553           throw INTERP_KERNEL::Exception(oss.str().c_str());
9554         }
9555     }
9556   arrOut=arro.retn();
9557   arrIndexOut=arrIo.retn();
9558 }
9559
9560 /*!
9561  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9562  * 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 ).
9563  * The selection of extraction is done standardly in new2old format.
9564  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9565  *
9566  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9567  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9568  * \param [in] arrIn arr origin array from which the extraction will be done.
9569  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9570  * \param [out] arrOut the resulting array
9571  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9572  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
9573  */
9574 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9575                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9576 {
9577   if(!arrIn || !arrIndxIn)
9578     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
9579   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9580   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9581     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
9582   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
9583   const int *arrInPtr=arrIn->getConstPointer();
9584   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9585   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9586   if(nbOfGrps<0)
9587     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9588   int maxSizeOfArr=arrIn->getNumberOfTuples();
9589   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9590   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9591   arrIo->alloc((int)(sz+1),1);
9592   int idsIt=idsOfSelectStart;
9593   int *work=arrIo->getPointer();
9594   *work++=0;
9595   int lgth=0;
9596   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
9597     {
9598       if(idsIt>=0 && idsIt<nbOfGrps)
9599         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
9600       else
9601         {
9602           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9603           throw INTERP_KERNEL::Exception(oss.str().c_str());
9604         }
9605       if(lgth>=work[-1])
9606         *work=lgth;
9607       else
9608         {
9609           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
9610           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
9611           throw INTERP_KERNEL::Exception(oss.str().c_str());
9612         }
9613     }
9614   arro->alloc(lgth,1);
9615   work=arro->getPointer();
9616   idsIt=idsOfSelectStart;
9617   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
9618     {
9619       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
9620         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
9621       else
9622         {
9623           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
9624           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9625           throw INTERP_KERNEL::Exception(oss.str().c_str());
9626         }
9627     }
9628   arrOut=arro.retn();
9629   arrIndexOut=arrIo.retn();
9630 }
9631
9632 /*!
9633  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9634  * 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
9635  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9636  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9637  *
9638  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9639  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9640  * \param [in] arrIn arr origin array from which the extraction will be done.
9641  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9642  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
9643  * \param [in] srcArrIndex index array of \b srcArr
9644  * \param [out] arrOut the resulting array
9645  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9646  * 
9647  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9648  */
9649 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9650                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9651                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9652 {
9653   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9654     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9655   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9656   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9657   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9658   std::vector<bool> v(nbOfTuples,true);
9659   int offset=0;
9660   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9661   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9662   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9663     {
9664       if(*it>=0 && *it<nbOfTuples)
9665         {
9666           v[*it]=false;
9667           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9668         }
9669       else
9670         {
9671           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9672           throw INTERP_KERNEL::Exception(oss.str().c_str());
9673         }
9674     }
9675   srcArrIndexPtr=srcArrIndex->getConstPointer();
9676   arrIo->alloc(nbOfTuples+1,1);
9677   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9678   const int *arrInPtr=arrIn->getConstPointer();
9679   const int *srcArrPtr=srcArr->getConstPointer();
9680   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9681   int *arroPtr=arro->getPointer();
9682   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9683     {
9684       if(v[ii])
9685         {
9686           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9687           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9688         }
9689       else
9690         {
9691           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9692           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9693           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9694         }
9695     }
9696   arrOut=arro.retn();
9697   arrIndexOut=arrIo.retn();
9698 }
9699
9700 /*!
9701  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9702  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9703  *
9704  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9705  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9706  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9707  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9708  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
9709  * \param [in] srcArrIndex index array of \b srcArr
9710  * 
9711  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9712  */
9713 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9714                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9715 {
9716   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9717     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9718   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9719   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9720   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9721   int *arrInOutPtr=arrInOut->getPointer();
9722   const int *srcArrPtr=srcArr->getConstPointer();
9723   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9724     {
9725       if(*it>=0 && *it<nbOfTuples)
9726         {
9727           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9728             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9729           else
9730             {
9731               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] !";
9732               throw INTERP_KERNEL::Exception(oss.str().c_str());
9733             }
9734         }
9735       else
9736         {
9737           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9738           throw INTERP_KERNEL::Exception(oss.str().c_str());
9739         }
9740     }
9741 }
9742
9743 /*!
9744  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9745  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9746  * 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]].
9747  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9748  * A negative value in \b arrIn means that it is ignored.
9749  * 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.
9750  * 
9751  * \param [in] arrIn arr origin array from which the extraction will be done.
9752  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9753  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9754  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9755  */
9756 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9757 {
9758   int seed=0,nbOfDepthPeelingPerformed=0;
9759   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9760 }
9761
9762 /*!
9763  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9764  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9765  * 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]].
9766  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9767  * A negative value in \b arrIn means that it is ignored.
9768  * 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.
9769  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9770  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9771  * \param [in] arrIn arr origin array from which the extraction will be done.
9772  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9773  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9774  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9775  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9776  * \sa MEDCouplingUMesh::partitionBySpreadZone
9777  */
9778 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9779 {
9780   nbOfDepthPeelingPerformed=0;
9781   if(!arrIndxIn)
9782     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9783   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9784   if(nbOfTuples<=0)
9785     {
9786       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9787       return ret;
9788     }
9789   //
9790   std::vector<bool> fetched(nbOfTuples,false);
9791   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9792 }
9793
9794 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9795 {
9796   nbOfDepthPeelingPerformed=0;
9797   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9798     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9799   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9800   std::vector<bool> fetched2(nbOfTuples,false);
9801   int i=0;
9802   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9803     {
9804       if(*seedElt>=0 && *seedElt<nbOfTuples)
9805         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9806       else
9807         { 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()); }
9808     }
9809   const int *arrInPtr=arrIn->getConstPointer();
9810   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9811   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9812   std::vector<int> idsToFetch1(seedBg,seedEnd);
9813   std::vector<int> idsToFetch2;
9814   std::vector<int> *idsToFetch=&idsToFetch1;
9815   std::vector<int> *idsToFetchOther=&idsToFetch2;
9816   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9817     {
9818       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9819         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9820           if(!fetched[*it2])
9821             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9822       std::swap(idsToFetch,idsToFetchOther);
9823       idsToFetchOther->clear();
9824       nbOfDepthPeelingPerformed++;
9825     }
9826   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9827   i=0;
9828   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9829   int *retPtr=ret->getPointer();
9830   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9831     if(*it)
9832       *retPtr++=i;
9833   return ret.retn();
9834 }
9835
9836 /*!
9837  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9838  * 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
9839  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9840  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9841  *
9842  * \param [in] start begin of set of ids of the input extraction (included)
9843  * \param [in] end end of set of ids of the input extraction (excluded)
9844  * \param [in] step step of the set of ids in range mode.
9845  * \param [in] arrIn arr origin array from which the extraction will be done.
9846  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9847  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9848  * \param [in] srcArrIndex index array of \b srcArr
9849  * \param [out] arrOut the resulting array
9850  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9851  * 
9852  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9853  */
9854 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9855                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9856                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9857 {
9858   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9859     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9860   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9861   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9862   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9863   int offset=0;
9864   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9865   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9866   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9867   int it=start;
9868   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9869     {
9870       if(it>=0 && it<nbOfTuples)
9871         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9872       else
9873         {
9874           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9875           throw INTERP_KERNEL::Exception(oss.str().c_str());
9876         }
9877     }
9878   srcArrIndexPtr=srcArrIndex->getConstPointer();
9879   arrIo->alloc(nbOfTuples+1,1);
9880   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9881   const int *arrInPtr=arrIn->getConstPointer();
9882   const int *srcArrPtr=srcArr->getConstPointer();
9883   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9884   int *arroPtr=arro->getPointer();
9885   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9886     {
9887       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9888       if(pos<0)
9889         {
9890           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9891           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9892         }
9893       else
9894         {
9895           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9896           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9897         }
9898     }
9899   arrOut=arro.retn();
9900   arrIndexOut=arrIo.retn();
9901 }
9902
9903 /*!
9904  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9905  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9906  *
9907  * \param [in] start begin of set of ids of the input extraction (included)
9908  * \param [in] end end of set of ids of the input extraction (excluded)
9909  * \param [in] step step of the set of ids in range mode.
9910  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9911  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9912  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9913  * \param [in] srcArrIndex index array of \b srcArr
9914  * 
9915  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9916  */
9917 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9918                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9919 {
9920   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9921     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9922   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9923   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9924   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9925   int *arrInOutPtr=arrInOut->getPointer();
9926   const int *srcArrPtr=srcArr->getConstPointer();
9927   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9928   int it=start;
9929   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9930     {
9931       if(it>=0 && it<nbOfTuples)
9932         {
9933           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9934             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9935           else
9936             {
9937               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9938               throw INTERP_KERNEL::Exception(oss.str().c_str());
9939             }
9940         }
9941       else
9942         {
9943           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9944           throw INTERP_KERNEL::Exception(oss.str().c_str());
9945         }
9946     }
9947 }
9948
9949 /*!
9950  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9951  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9952  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9953  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9954  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9955  * 
9956  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9957  */
9958 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
9959 {
9960   checkFullyDefined();
9961   int mdim=getMeshDimension();
9962   int spaceDim=getSpaceDimension();
9963   if(mdim!=spaceDim)
9964     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9965   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9966   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9967   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9968   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9969   ret->setCoords(getCoords());
9970   ret->allocateCells((int)partition.size());
9971   //
9972   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9973     {
9974       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9975       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9976       switch(mdim)
9977         {
9978         case 2:
9979           cell=tmp->buildUnionOf2DMesh();
9980           break;
9981         case 3:
9982           cell=tmp->buildUnionOf3DMesh();
9983           break;
9984         default:
9985           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9986         }
9987       
9988       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9989     }
9990   //
9991   ret->finishInsertingCells();
9992   return ret.retn();
9993 }
9994
9995 /*!
9996  * This method partitions \b this into contiguous zone.
9997  * This method only needs a well defined connectivity. Coordinates are not considered here.
9998  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9999  */
10000 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
10001 {
10002   int nbOfCellsCur=getNumberOfCells();
10003   std::vector<DataArrayInt *> ret;
10004   if(nbOfCellsCur<=0)
10005     return ret;
10006   DataArrayInt *neigh=0,*neighI=0;
10007   computeNeighborsOfCells(neigh,neighI);
10008   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
10009   std::vector<bool> fetchedCells(nbOfCellsCur,false);
10010   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
10011   int seed=0;
10012   while(seed<nbOfCellsCur)
10013     {
10014       int nbOfPeelPerformed=0;
10015       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
10016       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
10017     }
10018   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
10019     ret.push_back((*it).retn());
10020   return ret;
10021 }
10022
10023 /*!
10024  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
10025  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
10026  *
10027  * \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.
10028  * \return a newly allocated DataArrayInt to be managed by the caller.
10029  * \throw In case of \a code has not the right format (typically of size 3*n)
10030  */
10031 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
10032 {
10033   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
10034   std::size_t nb=code.size()/3;
10035   if(code.size()%3!=0)
10036     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
10037   ret->alloc((int)nb,2);
10038   int *retPtr=ret->getPointer();
10039   for(std::size_t i=0;i<nb;i++,retPtr+=2)
10040     {
10041       retPtr[0]=code[3*i+2];
10042       retPtr[1]=code[3*i+2]+code[3*i+1];
10043     }
10044   return ret.retn();
10045 }
10046
10047 /*!
10048  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
10049  * All cells in \a this are expected to be linear 3D cells.
10050  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
10051  * It leads to an increase to number of cells.
10052  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
10053  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
10054  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
10055  *
10056  * \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.
10057  *                      For all other cells, the splitting policy will be ignored.
10058  * \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. 
10059  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
10060  *          an id of old cell producing it. The caller is to delete this array using
10061  *         decrRef() as it is no more needed.
10062  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
10063  *
10064  * \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
10065  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
10066  * 
10067  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
10068  * \throw If \a this is not fully constituted with linear 3D cells.
10069  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
10070  */
10071 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
10072 {
10073   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
10074   checkConnectivityFullyDefined();
10075   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10076     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
10077   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
10078   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
10079   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
10080   int *retPt(ret->getPointer());
10081   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
10082   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
10083   const int *oldc(_nodal_connec->begin());
10084   const int *oldci(_nodal_connec_index->begin());
10085   const double *coords(_coords->begin());
10086   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
10087     {
10088       std::vector<int> a; std::vector<double> b;
10089       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
10090       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
10091       const int *aa(&a[0]);
10092       if(!b.empty())
10093         {
10094           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
10095             if(*it<0)
10096               *it=(-(*(it))-1+nbNodes);
10097           addPts->insertAtTheEnd(b.begin(),b.end());
10098           nbNodes+=(int)b.size()/3;
10099         }
10100       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
10101         newConn->insertAtTheEnd(aa,aa+4);
10102     }
10103   if(!addPts->empty())
10104     {
10105       addPts->rearrange(3);
10106       nbOfAdditionalPoints=addPts->getNumberOfTuples();
10107       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
10108       ret0->setCoords(addPts);
10109     }
10110   else
10111     {
10112       nbOfAdditionalPoints=0;
10113       ret0->setCoords(getCoords());
10114     }
10115   ret0->setNodalConnectivity(newConn);
10116   //
10117   ret->computeOffsets2();
10118   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
10119   return ret0.retn();
10120 }
10121
10122 /*!
10123  * It is the linear part of MEDCouplingUMesh::split2DCells. Here no additionnal nodes will be added in \b this. So coordinates pointer remain unchanged (is not even touch). 
10124  *
10125  * \sa MEDCouplingUMesh::split2DCells
10126  */
10127 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
10128 {
10129   checkConnectivityFullyDefined();
10130   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
10131   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10132   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10133   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10134   int prevPosOfCi(ciPtr[0]);
10135   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10136     {
10137       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
10138       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
10139       for(int j=0;j<sz;j++)
10140         {
10141           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
10142           for(int k=0;k<sz2;k++)
10143             *cPtr++=subPtr[offset2+k];
10144           if(j!=sz-1)
10145             *cPtr++=oldConn[prevPosOfCi+j+2];
10146           deltaSz+=sz2;
10147         }
10148       prevPosOfCi=ciPtr[1];
10149       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10150     }
10151   if(c->end()!=cPtr)
10152     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
10153   _nodal_connec->decrRef();
10154   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
10155 }
10156
10157 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
10158 {
10159   if(id!=-1)
10160     return id;
10161   else
10162     {
10163       int ret(nodesCnter++);
10164       double newPt[2];
10165       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
10166       addCoo.insertAtTheEnd(newPt,newPt+2);
10167       return ret;
10168     }
10169 }
10170
10171 /// @cond INTERNAL
10172
10173 void EnterTheResultOf2DCellFirst(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
10174 {
10175   int tmp[3];
10176   int trueStart(start>=0?start:nbOfEdges+start);
10177   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
10178   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
10179   if(linOrArc)
10180     {
10181       if(stp-start>1)
10182         {
10183           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10184           InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
10185           middles.push_back(tmp3+offset);
10186         }
10187       else
10188         middles.push_back(connBg[trueStart+nbOfEdges]);
10189     }
10190 }
10191
10192 void EnterTheResultOf2DCellMiddle(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
10193 {
10194   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
10195   newConnOfCell->pushBackSilent(tmpEnd);
10196   if(linOrArc)
10197     {
10198       if(stp-start>1)
10199         {
10200           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10201           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
10202           middles.push_back(tmp3+offset);
10203         }
10204       else
10205         middles.push_back(connBg[start+nbOfEdges]);
10206     }
10207 }
10208
10209 void EnterTheResultOf2DCellEnd(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
10210 {
10211   if(linOrArc)
10212     {
10213       if(stp-start>1)
10214         {
10215           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
10216           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10217           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
10218           middles.push_back(tmp3+offset);
10219         }
10220       else
10221         middles.push_back(connBg[start+nbOfEdges]);
10222     }
10223 }
10224
10225 /// @cond INTERNAL
10226
10227 /*!
10228  * Returns true if a colinearization has been found in the given cell. If false is returned the content pushed in \a newConnOfCell is equal to [ \a connBg , \a connEnd ) .
10229  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
10230  */
10231 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
10232 {
10233   std::size_t sz(std::distance(connBg,connEnd));
10234   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
10235     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
10236   sz--;
10237   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
10238   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
10239   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
10240   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
10241   INTERP_KERNEL::NormalizedCellType typeOfSon;
10242   std::vector<int> middles;
10243   bool ret(false);
10244   for(;nbOfHit<nbs;nbOfTurn++)
10245     {
10246       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
10247       std::map<INTERP_KERNEL::Node *,int> m;
10248       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
10249       posEndElt++;
10250       nbOfHit++;
10251       unsigned endI(nbs-nbOfHit);
10252       for(unsigned i=0;i<endI;i++)
10253         {
10254           cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
10255           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
10256           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
10257           bool isColinear(eint->areColinears());
10258           if(isColinear)
10259             {
10260               nbOfHit++;
10261               posEndElt++;
10262               ret=true;
10263             }
10264           delete eint;
10265           eCand->decrRef();
10266           if(!isColinear)
10267             {
10268               if(nbOfTurn==0)
10269                 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
10270                   unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
10271                   for(unsigned ii=0;ii<endII;ii++)
10272                     {
10273                       cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
10274                       eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
10275                       eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
10276                       isColinear=eint->areColinears();
10277                       if(isColinear)
10278                         {
10279                           nbOfHit++;
10280                           posBaseElt--;
10281                           ret=true;
10282                         }
10283                       delete eint;
10284                       eCand->decrRef();
10285                     }
10286                 }
10287               break;
10288             }
10289         }
10290       //push [posBaseElt,posEndElt) in newConnOfCell using e
10291       if(nbOfTurn==0)
10292         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10293       else if(nbOfHit!=nbs)
10294         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10295       else
10296         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10297       posBaseElt=posEndElt;
10298       for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it=m.begin();it!=m.end();it++)
10299         (*it).first->decrRef();
10300       e->decrRef();
10301     }
10302   if(!middles.empty())
10303     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
10304   return ret;
10305 }
10306
10307 /*!
10308  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
10309  *
10310  * \return  int - the number of new nodes created.
10311  * \sa MEDCouplingUMesh::split2DCells
10312  */
10313 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
10314 {
10315   checkCoherency();
10316   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
10317   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10318   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
10319   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10320   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
10321   const double *oldCoordsPtr(getCoords()->begin());
10322   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10323   int prevPosOfCi(ciPtr[0]);
10324   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10325     {
10326       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
10327       for(int j=0;j<sz;j++)
10328         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
10329       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
10330       for(int j=0;j<sz;j++)//loop over subedges of oldConn
10331         {
10332           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
10333           if(sz2==0)
10334             {
10335               if(j<sz-1)
10336                 cPtr[1]=oldConn[prevPosOfCi+2+j];
10337               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
10338               continue;
10339             }
10340           std::vector<INTERP_KERNEL::Node *> ns(3);
10341           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
10342           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
10343           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
10344           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
10345           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
10346             {
10347               cPtr[1]=subPtr[offset2+k];
10348               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
10349             }
10350           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
10351           if(j!=sz-1)
10352             { cPtr[1]=tmpEnd; }
10353           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
10354         }
10355       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
10356       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10357     }
10358   if(c->end()!=cPtr)
10359     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
10360   _nodal_connec->decrRef();
10361   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
10362   addCoo->rearrange(2);
10363   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
10364   setCoords(coo);
10365   return addCoo->getNumberOfTuples();
10366 }
10367
10368 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
10369                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
10370 {
10371   if(mesh)
10372     {
10373       mesh->incrRef();
10374       _nb_cell=mesh->getNumberOfCells();
10375     }
10376 }
10377
10378 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
10379 {
10380   if(_mesh)
10381     _mesh->decrRef();
10382   if(_own_cell)
10383     delete _cell;
10384 }
10385
10386 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
10387                                                                                                                                _own_cell(false),_cell_id(bg-1),
10388                                                                                                                                _nb_cell(end)
10389 {
10390   if(mesh)
10391     mesh->incrRef();
10392 }
10393
10394 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
10395 {
10396   _cell_id++;
10397   if(_cell_id<_nb_cell)
10398     {
10399       _cell->next();
10400       return _cell;
10401     }
10402   else
10403     return 0;
10404 }
10405
10406 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
10407 {
10408   if(_mesh)
10409     _mesh->incrRef();
10410 }
10411
10412 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
10413 {
10414   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
10415 }
10416
10417 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
10418 {
10419   if(_mesh)
10420     _mesh->decrRef();
10421 }
10422
10423 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
10424                                                                                                                                                                   _itc(itc),
10425                                                                                                                                                                   _bg(bg),_end(end)
10426 {
10427   if(_mesh)
10428     _mesh->incrRef();
10429 }
10430
10431 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
10432 {
10433   if(_mesh)
10434     _mesh->decrRef();
10435 }
10436
10437 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
10438 {
10439   return _type;
10440 }
10441
10442 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
10443 {
10444   return _end-_bg;
10445 }
10446
10447 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
10448 {
10449   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
10450 }
10451
10452 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
10453 {
10454   if(mesh)
10455     {
10456       mesh->incrRef();
10457       _nb_cell=mesh->getNumberOfCells();
10458     }
10459 }
10460
10461 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
10462 {
10463   if(_mesh)
10464     _mesh->decrRef();
10465   delete _cell;
10466 }
10467
10468 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
10469 {
10470   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
10471   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
10472   if(_cell_id<_nb_cell)
10473     {
10474       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
10475       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
10476       int startId=_cell_id;
10477       _cell_id+=nbOfElems;
10478       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
10479     }
10480   else
10481     return 0;
10482 }
10483
10484 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
10485 {
10486   if(mesh)
10487     {
10488       _conn=mesh->getNodalConnectivity()->getPointer();
10489       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
10490     }
10491 }
10492
10493 void MEDCouplingUMeshCell::next()
10494 {
10495   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10496     {
10497       _conn+=_conn_lgth;
10498       _conn_indx++;
10499     }
10500   _conn_lgth=_conn_indx[1]-_conn_indx[0];
10501 }
10502
10503 std::string MEDCouplingUMeshCell::repr() const
10504 {
10505   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10506     {
10507       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
10508       oss << " : ";
10509       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
10510       return oss.str();
10511     }
10512   else
10513     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
10514 }
10515
10516 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
10517 {
10518   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10519     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
10520   else
10521     return INTERP_KERNEL::NORM_ERROR;
10522 }
10523
10524 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
10525 {
10526   lgth=_conn_lgth;
10527   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10528     return _conn;
10529   else
10530     return 0;
10531 }