Salome HOME
stash0
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
42
43 #include <sstream>
44 #include <fstream>
45 #include <numeric>
46 #include <cstring>
47 #include <limits>
48 #include <list>
49
50 using namespace ParaMEDMEM;
51
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53
54 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
55
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 {
58   return new MEDCouplingUMesh;
59 }
60
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
62 {
63   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64   ret->setName(meshName);
65   ret->setMeshDimension(meshDim);
66   return ret;
67 }
68
69 /*!
70  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71  * between \a this and the new mesh.
72  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73  *          delete this mesh using decrRef() as it is no more needed. 
74  */
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
76 {
77   return clone(true);
78 }
79
80 /*!
81  * Returns a new MEDCouplingMesh which is a copy of \a this one.
82  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83  * this mesh are shared by the new mesh.
84  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85  *          delete this mesh using decrRef() as it is no more needed. 
86  */
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
88 {
89   return new MEDCouplingUMesh(*this,recDeepCpy);
90 }
91
92 /*!
93  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94  * The coordinates are shared between \a this and the returned instance.
95  * 
96  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97  * \sa MEDCouplingUMesh::deepCpy
98  */
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
100 {
101   checkConnectivityFullyDefined();
102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104   ret->setConnectivity(c,ci);
105   return ret.retn();
106 }
107
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
109 {
110   if(!other)
111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
113   if(!otherC)
114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
117 }
118
119 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
120 {
121   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
122   return ret;
123 }
124
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildren() const
126 {
127   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildren());
128   if(_nodal_connec)
129     ret.push_back(_nodal_connec);
130   if(_nodal_connec_index)
131     ret.push_back(_nodal_connec_index);
132   return ret;
133 }
134
135 void MEDCouplingUMesh::updateTime() const
136 {
137   MEDCouplingPointSet::updateTime();
138   if(_nodal_connec)
139     {
140       updateTimeWith(*_nodal_connec);
141     }
142   if(_nodal_connec_index)
143     {
144       updateTimeWith(*_nodal_connec_index);
145     }
146 }
147
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
149 {
150 }
151
152 /*!
153  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154  * then \a this mesh is most probably is writable, exchangeable and available for most
155  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156  * this method to check that all is in order with \a this mesh.
157  *  \throw If the mesh dimension is not set.
158  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
159  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160  *  \throw If the connectivity data array has more than one component.
161  *  \throw If the connectivity data array has a named component.
162  *  \throw If the connectivity index data array has more than one component.
163  *  \throw If the connectivity index data array has a named component.
164  */
165 void MEDCouplingUMesh::checkCoherency() const
166 {
167   if(_mesh_dim<-1)
168     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
169   if(_mesh_dim!=-1)
170     MEDCouplingPointSet::checkCoherency();
171   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
172     {
173       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
174         {
175           std::ostringstream message;
176           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177           throw INTERP_KERNEL::Exception(message.str().c_str());
178         }
179     }
180   if(_nodal_connec)
181     {
182       if(_nodal_connec->getNumberOfComponents()!=1)
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184       if(_nodal_connec->getInfoOnComponent(0)!="")
185         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
186     }
187   else
188     if(_mesh_dim!=-1)
189       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190   if(_nodal_connec_index)
191     {
192       if(_nodal_connec_index->getNumberOfComponents()!=1)
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194       if(_nodal_connec_index->getInfoOnComponent(0)!="")
195         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
196     }
197   else
198     if(_mesh_dim!=-1)
199       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
200 }
201
202 /*!
203  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204  * then \a this mesh is most probably is writable, exchangeable and available for all
205  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206  * method thoroughly checks the nodal connectivity.
207  *  \param [in] eps - a not used parameter.
208  *  \throw If the mesh dimension is not set.
209  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
210  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211  *  \throw If the connectivity data array has more than one component.
212  *  \throw If the connectivity data array has a named component.
213  *  \throw If the connectivity index data array has more than one component.
214  *  \throw If the connectivity index data array has a named component.
215  *  \throw If number of nodes defining an element does not correspond to the type of element.
216  *  \throw If the nodal connectivity includes an invalid node id.
217  */
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
219 {
220   checkCoherency();
221   if(_mesh_dim==-1)
222     return ;
223   int meshDim=getMeshDimension();
224   int nbOfNodes=getNumberOfNodes();
225   int nbOfCells=getNumberOfCells();
226   const int *ptr=_nodal_connec->getConstPointer();
227   const int *ptrI=_nodal_connec_index->getConstPointer();
228   for(int i=0;i<nbOfCells;i++)
229     {
230       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231       if((int)cm.getDimension()!=meshDim)
232         {
233           std::ostringstream oss;
234           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235           throw INTERP_KERNEL::Exception(oss.str().c_str());
236         }
237       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
238       if(!cm.isDynamic())
239         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
240           {
241             std::ostringstream oss;
242             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
243             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244             throw INTERP_KERNEL::Exception(oss.str().c_str());
245           }
246       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
247         {
248           int nodeId=*w;
249           if(nodeId>=0)
250             {
251               if(nodeId>=nbOfNodes)
252                 {
253                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
254                   throw INTERP_KERNEL::Exception(oss.str().c_str());
255                 }
256             }
257           else if(nodeId<-1)
258             {
259               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
260               throw INTERP_KERNEL::Exception(oss.str().c_str());
261             }
262           else
263             {
264               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
265                 {
266                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
267                   throw INTERP_KERNEL::Exception(oss.str().c_str());
268                 }
269             }
270         }
271     }
272 }
273
274
275 /*!
276  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
277  * then \a this mesh is most probably is writable, exchangeable and available for all
278  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
279  *  \param [in] eps - a not used parameter.
280  *  \throw If the mesh dimension is not set.
281  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
282  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
283  *  \throw If the connectivity data array has more than one component.
284  *  \throw If the connectivity data array has a named component.
285  *  \throw If the connectivity index data array has more than one component.
286  *  \throw If the connectivity index data array has a named component.
287  *  \throw If number of nodes defining an element does not correspond to the type of element.
288  *  \throw If the nodal connectivity includes an invalid node id.
289  */
290 void MEDCouplingUMesh::checkCoherency2(double eps) const
291 {
292   checkCoherency1(eps);
293 }
294
295 /*!
296  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
297  * elements contained in the mesh. For more info on the mesh dimension see
298  * \ref MEDCouplingUMeshPage.
299  *  \param [in] meshDim - a new mesh dimension.
300  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
301  */
302 void MEDCouplingUMesh::setMeshDimension(int meshDim)
303 {
304   if(meshDim<-1 || meshDim>3)
305     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
306   _mesh_dim=meshDim;
307   declareAsNew();
308 }
309
310 /*!
311  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
312  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
313  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
314  *
315  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
316  *
317  *  \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 neighbor cells of cell having id 'cellId' 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 neighbor cells of cell having id 'cellId' 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)
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 /*!
876  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
877  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
878  * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
879  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
880  *
881  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
882  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
883  * \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.
884  */
885 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
886 {
887   checkFullyDefined();
888   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
889   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
890   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
891   switch(mdim)
892   {
893     case 3:
894       {
895         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
896         break;
897       }
898     case 2:
899       {
900         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
901         break;
902       }
903     case 1:
904       {
905         mesh1D=const_cast<MEDCouplingUMesh *>(this);
906         mesh1D->incrRef();
907         break;
908       }
909     default:
910       {
911         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
912       }
913   }
914   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
915   mesh1D->getReverseNodalConnectivity(desc,descIndx);
916   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
917   ret0->alloc(desc->getNumberOfTuples(),1);
918   int *r0Pt(ret0->getPointer());
919   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
920   for(int i=0;i<nbNodes;i++,rni++)
921     {
922       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
923         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
924     }
925   neighbors=ret0.retn();
926   neighborsIdx=descIndx.retn();
927 }
928
929 /// @cond INTERNAL
930
931 /*!
932  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
933  * For speed reasons no check of this will be done.
934  */
935 template<class SonsGenerator>
936 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
937 {
938   if(!desc || !descIndx || !revDesc || !revDescIndx)
939     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
940   checkConnectivityFullyDefined();
941   int nbOfCells=getNumberOfCells();
942   int nbOfNodes=getNumberOfNodes();
943   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
944   int *revNodalIndxPtr=revNodalIndx->getPointer();
945   const int *conn=_nodal_connec->getConstPointer();
946   const int *connIndex=_nodal_connec_index->getConstPointer();
947   std::string name="Mesh constituent of "; name+=getName();
948   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
949   ret->setCoords(getCoords());
950   ret->allocateCells(2*nbOfCells);
951   descIndx->alloc(nbOfCells+1,1);
952   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
953   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
954   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
955     {
956       int pos=connIndex[eltId];
957       int posP1=connIndex[eltId+1];
958       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
959       SonsGenerator sg(cm);
960       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
961       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
962       for(unsigned i=0;i<nbOfSons;i++)
963         {
964           INTERP_KERNEL::NormalizedCellType cmsId;
965           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
966           for(unsigned k=0;k<nbOfNodesSon;k++)
967             if(tmp[k]>=0)
968               revNodalIndxPtr[tmp[k]+1]++;
969           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
970           revDesc2->pushBackSilent(eltId);
971         }
972       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
973     }
974   int nbOfCellsM1=ret->getNumberOfCells();
975   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
976   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
977   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
978   int *revNodalPtr=revNodal->getPointer();
979   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
980   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
981   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
982     {
983       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
984       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
985       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
986         if(*iter>=0)//for polyhedrons
987           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
988     }
989   //
990   DataArrayInt *commonCells=0,*commonCellsI=0;
991   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
992   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
993   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
994   int newNbOfCellsM1=-1;
995   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
996                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
997   std::vector<bool> isImpacted(nbOfCellsM1,false);
998   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
999     for(int work2=work[0];work2!=work[1];work2++)
1000       isImpacted[commonCellsPtr[work2]]=true;
1001   const int *o2nM1Ptr=o2nM1->getConstPointer();
1002   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1003   const int *n2oM1Ptr=n2oM1->getConstPointer();
1004   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1005   ret2->copyTinyInfoFrom(this);
1006   desc->alloc(descIndx->back(),1);
1007   int *descPtr=desc->getPointer();
1008   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1009   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1010     {
1011       if(!isImpacted[i])
1012         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1013       else
1014         {
1015           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1016             {
1017               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1018               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1019             }
1020           else
1021             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1022         }
1023     }
1024   revDesc->reserve(newNbOfCellsM1);
1025   revDescIndx->alloc(newNbOfCellsM1+1,1);
1026   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1027   const int *revDesc2Ptr=revDesc2->getConstPointer();
1028   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1029     {
1030       int oldCellIdM1=n2oM1Ptr[i];
1031       if(!isImpacted[oldCellIdM1])
1032         {
1033           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1034           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1035         }
1036       else
1037         {
1038           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1039             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1040           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1041           commonCellsIPtr++;
1042         }
1043     }
1044   //
1045   return ret2.retn();
1046 }
1047
1048 struct MEDCouplingAccVisit
1049 {
1050   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1051   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1052   int _new_nb_of_nodes;
1053 };
1054
1055 /// @endcond
1056
1057 /*!
1058  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1059  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1060  * array of cell ids. Pay attention that after conversion all algorithms work slower
1061  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1062  * conversion due presence of invalid ids in the array of cells to convert, as a
1063  * result \a this mesh contains some already converted elements. In this case the 2D
1064  * mesh remains valid but 3D mesh becomes \b inconsistent!
1065  *  \warning This method can significantly modify the order of geometric types in \a this,
1066  *          hence, to write this mesh to the MED file, its cells must be sorted using
1067  *          sortCellsInMEDFileFrmt().
1068  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1069  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1070  *         cellIdsToConvertBg.
1071  *  \throw If the coordinates array is not set.
1072  *  \throw If the nodal connectivity of cells is node defined.
1073  *  \throw If dimension of \a this mesh is not either 2 or 3.
1074  *
1075  *  \if ENABLE_EXAMPLES
1076  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1077  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1078  *  \endif
1079  */
1080 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1081 {
1082   checkFullyDefined();
1083   int dim=getMeshDimension();
1084   if(dim<2 || dim>3)
1085     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1086   int nbOfCells(getNumberOfCells());
1087   if(dim==2)
1088     {
1089       const int *connIndex=_nodal_connec_index->getConstPointer();
1090       int *conn=_nodal_connec->getPointer();
1091       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1092         {
1093           if(*iter>=0 && *iter<nbOfCells)
1094             {
1095               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1096               if(!cm.isQuadratic())
1097                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1098               else
1099                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1100             }
1101           else
1102             {
1103               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1104               oss << " in range [0," << nbOfCells << ") !";
1105               throw INTERP_KERNEL::Exception(oss.str().c_str());
1106             }
1107         }
1108     }
1109   else
1110     {
1111       int *connIndex(_nodal_connec_index->getPointer());
1112       const int *connOld(_nodal_connec->getConstPointer());
1113       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1114       std::vector<bool> toBeDone(nbOfCells,false);
1115       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1116         {
1117           if(*iter>=0 && *iter<nbOfCells)
1118             toBeDone[*iter]=true;
1119           else
1120             {
1121               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1122               oss << " in range [0," << nbOfCells << ") !";
1123               throw INTERP_KERNEL::Exception(oss.str().c_str());
1124             }
1125         }
1126       for(int cellId=0;cellId<nbOfCells;cellId++)
1127         {
1128           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1129           int lgthOld(posP1-pos-1);
1130           if(toBeDone[cellId])
1131             {
1132               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1133               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1134               int *tmp(new int[nbOfFaces*lgthOld+1]);
1135               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1136               for(unsigned j=0;j<nbOfFaces;j++)
1137                 {
1138                   INTERP_KERNEL::NormalizedCellType type;
1139                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1140                   work+=offset;
1141                   *work++=-1;
1142                 }
1143               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1144               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1145               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1146               delete [] tmp;
1147             }
1148           else
1149             {
1150               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1151               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1152             }
1153         }
1154       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1155     }
1156   computeTypes();
1157 }
1158
1159 /*!
1160  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1161  * polyhedrons (if \a this is a 3D mesh).
1162  *  \warning As this method is purely for user-friendliness and no optimization is
1163  *          done to avoid construction of a useless vector, this method can be costly
1164  *          in memory.
1165  *  \throw If the coordinates array is not set.
1166  *  \throw If the nodal connectivity of cells is node defined.
1167  *  \throw If dimension of \a this mesh is not either 2 or 3.
1168  */
1169 void MEDCouplingUMesh::convertAllToPoly()
1170 {
1171   int nbOfCells=getNumberOfCells();
1172   std::vector<int> cellIds(nbOfCells);
1173   for(int i=0;i<nbOfCells;i++)
1174     cellIds[i]=i;
1175   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1176 }
1177
1178 /*!
1179  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1180  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1181  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1182  * base facet of the volume and the second half of nodes describes an opposite facet
1183  * having the same number of nodes as the base one. This method converts such
1184  * connectivity to a valid polyhedral format where connectivity of each facet is
1185  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1186  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1187  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1188  * a correct orientation of the first facet of a polyhedron, else orientation of a
1189  * corrected cell is reverse.<br>
1190  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1191  * it releases the user from boring description of polyhedra connectivity in the valid
1192  * format.
1193  *  \throw If \a this->getMeshDimension() != 3.
1194  *  \throw If \a this->getSpaceDimension() != 3.
1195  *  \throw If the nodal connectivity of cells is not defined.
1196  *  \throw If the coordinates array is not set.
1197  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1198  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1199  *
1200  *  \if ENABLE_EXAMPLES
1201  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1202  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1203  *  \endif
1204  */
1205 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1206 {
1207   checkFullyDefined();
1208   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1209     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1210   int nbOfCells=getNumberOfCells();
1211   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1212   newCi->alloc(nbOfCells+1,1);
1213   int *newci=newCi->getPointer();
1214   const int *ci=_nodal_connec_index->getConstPointer();
1215   const int *c=_nodal_connec->getConstPointer();
1216   newci[0]=0;
1217   for(int i=0;i<nbOfCells;i++)
1218     {
1219       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1220       if(type==INTERP_KERNEL::NORM_POLYHED)
1221         {
1222           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1223             {
1224               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1225               throw INTERP_KERNEL::Exception(oss.str().c_str());
1226             }
1227           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1228           if(n2%2!=0)
1229             {
1230               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 !";
1231               throw INTERP_KERNEL::Exception(oss.str().c_str());
1232             }
1233           int n1=(int)(n2/2);
1234           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)
1235         }
1236       else
1237         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1238     }
1239   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1240   newC->alloc(newci[nbOfCells],1);
1241   int *newc=newC->getPointer();
1242   for(int i=0;i<nbOfCells;i++)
1243     {
1244       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1245       if(type==INTERP_KERNEL::NORM_POLYHED)
1246         {
1247           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1248           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1249           *newc++=-1;
1250           for(std::size_t j=0;j<n1;j++)
1251             {
1252               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1253               newc[n1+5*j]=-1;
1254               newc[n1+5*j+1]=c[ci[i]+1+j];
1255               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1256               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1257               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1258             }
1259           newc+=n1*6;
1260         }
1261       else
1262         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1263     }
1264   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1265   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1266 }
1267
1268
1269 /*!
1270  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1271  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1272  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1273  *          to write this mesh to the MED file, its cells must be sorted using
1274  *          sortCellsInMEDFileFrmt().
1275  * \return \c true if at least one cell has been converted, \c false else. In the
1276  *         last case the nodal connectivity remains unchanged.
1277  * \throw If the coordinates array is not set.
1278  * \throw If the nodal connectivity of cells is not defined.
1279  * \throw If \a this->getMeshDimension() < 0.
1280  */
1281 bool MEDCouplingUMesh::unPolyze()
1282 {
1283   checkFullyDefined();
1284   int mdim=getMeshDimension();
1285   if(mdim<0)
1286     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1287   if(mdim<=1)
1288     return false;
1289   int nbOfCells=getNumberOfCells();
1290   if(nbOfCells<1)
1291     return false;
1292   int initMeshLgth=getMeshLength();
1293   int *conn=_nodal_connec->getPointer();
1294   int *index=_nodal_connec_index->getPointer();
1295   int posOfCurCell=0;
1296   int newPos=0;
1297   int lgthOfCurCell;
1298   bool ret=false;
1299   for(int i=0;i<nbOfCells;i++)
1300     {
1301       lgthOfCurCell=index[i+1]-posOfCurCell;
1302       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1303       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1304       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1305       int newLgth;
1306       if(cm.isDynamic())
1307         {
1308           switch(cm.getDimension())
1309           {
1310             case 2:
1311               {
1312                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1313                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1314                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1315                 break;
1316               }
1317             case 3:
1318               {
1319                 int nbOfFaces,lgthOfPolyhConn;
1320                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1321                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1322                 break;
1323               }
1324             case 1:
1325               {
1326                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1327                 break;
1328               }
1329           }
1330           ret=ret || (newType!=type);
1331           conn[newPos]=newType;
1332           newPos+=newLgth+1;
1333           posOfCurCell=index[i+1];
1334           index[i+1]=newPos;
1335         }
1336       else
1337         {
1338           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1339           newPos+=lgthOfCurCell;
1340           posOfCurCell+=lgthOfCurCell;
1341           index[i+1]=newPos;
1342         }
1343     }
1344   if(newPos!=initMeshLgth)
1345     _nodal_connec->reAlloc(newPos);
1346   if(ret)
1347     computeTypes();
1348   return ret;
1349 }
1350
1351 /*!
1352  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1353  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1354  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1355  *
1356  * \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 
1357  *             precision.
1358  */
1359 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1360 {
1361   checkFullyDefined();
1362   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1363     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1364   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1365   coords->recenterForMaxPrecision(eps);
1366   //
1367   int nbOfCells=getNumberOfCells();
1368   const int *conn=_nodal_connec->getConstPointer();
1369   const int *index=_nodal_connec_index->getConstPointer();
1370   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1371   connINew->alloc(nbOfCells+1,1);
1372   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1373   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1374   bool changed=false;
1375   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1376     {
1377       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1378         {
1379           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1380           changed=true;
1381         }
1382       else
1383         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1384       *connINewPtr=connNew->getNumberOfTuples();
1385     }
1386   if(changed)
1387     setConnectivity(connNew,connINew,false);
1388 }
1389
1390 /*!
1391  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1392  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1393  * the format of returned DataArrayInt instance.
1394  * 
1395  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1396  * \sa MEDCouplingUMesh::getNodeIdsInUse
1397  */
1398 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1399 {
1400   checkConnectivityFullyDefined();
1401   int nbOfCells=getNumberOfCells();
1402   const int *connIndex=_nodal_connec_index->getConstPointer();
1403   const int *conn=_nodal_connec->getConstPointer();
1404   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1405   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1406   std::vector<bool> retS(maxElt,false);
1407   for(int i=0;i<nbOfCells;i++)
1408     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1409       if(conn[j]>=0)
1410         retS[conn[j]]=true;
1411   int sz=0;
1412   for(int i=0;i<maxElt;i++)
1413     if(retS[i])
1414       sz++;
1415   DataArrayInt *ret=DataArrayInt::New();
1416   ret->alloc(sz,1);
1417   int *retPtr=ret->getPointer();
1418   for(int i=0;i<maxElt;i++)
1419     if(retS[i])
1420       *retPtr++=i;
1421   return ret;
1422 }
1423
1424 /*!
1425  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1426  * \sa MEDCouplingUMesh::getNodeIdsInUse
1427  */
1428 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1429 {
1430   int nbOfNodes=(int)nodeIdsInUse.size();
1431   int nbOfCells=getNumberOfCells();
1432   const int *connIndex=_nodal_connec_index->getConstPointer();
1433   const int *conn=_nodal_connec->getConstPointer();
1434   for(int i=0;i<nbOfCells;i++)
1435     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1436       if(conn[j]>=0)
1437         {
1438           if(conn[j]<nbOfNodes)
1439             nodeIdsInUse[conn[j]]=true;
1440           else
1441             {
1442               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1443               throw INTERP_KERNEL::Exception(oss.str().c_str());
1444             }
1445         }
1446 }
1447
1448 /*!
1449  * Finds nodes not used in any cell and returns an array giving a new id to every node
1450  * by excluding the unused nodes, for which the array holds -1. The result array is
1451  * a mapping in "Old to New" mode. 
1452  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1453  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1454  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1455  *          if the node is unused or a new id else. The caller is to delete this
1456  *          array using decrRef() as it is no more needed.  
1457  *  \throw If the coordinates array is not set.
1458  *  \throw If the nodal connectivity of cells is not defined.
1459  *  \throw If the nodal connectivity includes an invalid id.
1460  *
1461  *  \if ENABLE_EXAMPLES
1462  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1463  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1464  *  \endif
1465  * \sa computeNodeIdsAlg()
1466  */
1467 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1468 {
1469   nbrOfNodesInUse=-1;
1470   int nbOfNodes=getNumberOfNodes();
1471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1472   ret->alloc(nbOfNodes,1);
1473   int *traducer=ret->getPointer();
1474   std::fill(traducer,traducer+nbOfNodes,-1);
1475   int nbOfCells=getNumberOfCells();
1476   const int *connIndex=_nodal_connec_index->getConstPointer();
1477   const int *conn=_nodal_connec->getConstPointer();
1478   for(int i=0;i<nbOfCells;i++)
1479     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1480       if(conn[j]>=0)
1481         {
1482           if(conn[j]<nbOfNodes)
1483             traducer[conn[j]]=1;
1484           else
1485             {
1486               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1487               throw INTERP_KERNEL::Exception(oss.str().c_str());
1488             }
1489         }
1490   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1491   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1492   return ret.retn();
1493 }
1494
1495 /*!
1496  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1497  * For each cell in \b this the number of nodes constituting cell is computed.
1498  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1499  * So for pohyhedrons some nodes can be counted several times in the returned result.
1500  * 
1501  * \return a newly allocated array
1502  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1503  */
1504 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1505 {
1506   checkConnectivityFullyDefined();
1507   int nbOfCells=getNumberOfCells();
1508   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1509   ret->alloc(nbOfCells,1);
1510   int *retPtr=ret->getPointer();
1511   const int *conn=getNodalConnectivity()->getConstPointer();
1512   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1513   for(int i=0;i<nbOfCells;i++,retPtr++)
1514     {
1515       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1516         *retPtr=connI[i+1]-connI[i]-1;
1517       else
1518         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1519     }
1520   return ret.retn();
1521 }
1522
1523 /*!
1524  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1525  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1526  *
1527  * \return DataArrayInt * - new object to be deallocated by the caller.
1528  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1529  */
1530 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1531 {
1532   checkConnectivityFullyDefined();
1533   int nbOfCells=getNumberOfCells();
1534   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1535   ret->alloc(nbOfCells,1);
1536   int *retPtr=ret->getPointer();
1537   const int *conn=getNodalConnectivity()->getConstPointer();
1538   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1539   for(int i=0;i<nbOfCells;i++,retPtr++)
1540     {
1541       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1542       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1543         *retPtr=(int)s.size();
1544       else
1545         {
1546           s.erase(-1);
1547           *retPtr=(int)s.size();
1548         }
1549     }
1550   return ret.retn();
1551 }
1552
1553 /*!
1554  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1555  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1556  * 
1557  * \return a newly allocated array
1558  */
1559 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1560 {
1561   checkConnectivityFullyDefined();
1562   int nbOfCells=getNumberOfCells();
1563   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1564   ret->alloc(nbOfCells,1);
1565   int *retPtr=ret->getPointer();
1566   const int *conn=getNodalConnectivity()->getConstPointer();
1567   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1568   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1569     {
1570       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1571       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1572     }
1573   return ret.retn();
1574 }
1575
1576 /*!
1577  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1578  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1579  * array mean that the corresponding old node is no more used. 
1580  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1581  *           this->getNumberOfNodes() before call of this method. The caller is to
1582  *           delete this array using decrRef() as it is no more needed. 
1583  *  \throw If the coordinates array is not set.
1584  *  \throw If the nodal connectivity of cells is not defined.
1585  *  \throw If the nodal connectivity includes an invalid id.
1586  *
1587  *  \if ENABLE_EXAMPLES
1588  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1589  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1590  *  \endif
1591  */
1592 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1593 {
1594   return MEDCouplingPointSet::zipCoordsTraducer();
1595 }
1596
1597 /*!
1598  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1599  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1600  */
1601 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1602 {
1603   switch(compType)
1604   {
1605     case 0:
1606       return AreCellsEqual0(conn,connI,cell1,cell2);
1607     case 1:
1608       return AreCellsEqual1(conn,connI,cell1,cell2);
1609     case 2:
1610       return AreCellsEqual2(conn,connI,cell1,cell2);
1611     case 3:
1612       return AreCellsEqual3(conn,connI,cell1,cell2);
1613     case 7:
1614       return AreCellsEqual7(conn,connI,cell1,cell2);
1615   }
1616   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1617 }
1618
1619 /*!
1620  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1621  */
1622 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1623 {
1624   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1625     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1626   return 0;
1627 }
1628
1629 /*!
1630  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1631  */
1632 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1633 {
1634   int sz=connI[cell1+1]-connI[cell1];
1635   if(sz==connI[cell2+1]-connI[cell2])
1636     {
1637       if(conn[connI[cell1]]==conn[connI[cell2]])
1638         {
1639           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1640           unsigned dim=cm.getDimension();
1641           if(dim!=3)
1642             {
1643               if(dim!=1)
1644                 {
1645                   int sz1=2*(sz-1);
1646                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1647                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1648                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1649                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1650                   return work!=tmp+sz1?1:0;
1651                 }
1652               else
1653                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1654             }
1655           else
1656             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1657         }
1658     }
1659   return 0;
1660 }
1661
1662 /*!
1663  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1664  */
1665 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1666 {
1667   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1668     {
1669       if(conn[connI[cell1]]==conn[connI[cell2]])
1670         {
1671           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1672           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1673           return s1==s2?1:0;
1674         }
1675     }
1676   return 0;
1677 }
1678
1679 /*!
1680  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1681  */
1682 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1683 {
1684   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1685     {
1686       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1687       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1688       return s1==s2?1:0;
1689     }
1690   return 0;
1691 }
1692
1693 /*!
1694  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1695  */
1696 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1697 {
1698   int sz=connI[cell1+1]-connI[cell1];
1699   if(sz==connI[cell2+1]-connI[cell2])
1700     {
1701       if(conn[connI[cell1]]==conn[connI[cell2]])
1702         {
1703           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1704           unsigned dim=cm.getDimension();
1705           if(dim!=3)
1706             {
1707               if(dim!=1)
1708                 {
1709                   int sz1=2*(sz-1);
1710                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1711                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1712                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1713                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1714                   if(work!=tmp+sz1)
1715                     return 1;
1716                   else
1717                     {
1718                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1719                       std::reverse_iterator<int *> it2((int *)tmp);
1720                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1721                         return 2;
1722                       else
1723                         return 0;
1724                     }
1725
1726                   return work!=tmp+sz1?1:0;
1727                 }
1728               else
1729                 {//case of SEG2 and SEG3
1730                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1731                     return 1;
1732                   if(!cm.isQuadratic())
1733                     {
1734                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1735                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1736                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1737                         return 2;
1738                       return 0;
1739                     }
1740                   else
1741                     {
1742                       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])
1743                         return 2;
1744                       return 0;
1745                     }
1746                 }
1747             }
1748           else
1749             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1750         }
1751     }
1752   return 0;
1753 }
1754
1755 /*!
1756  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1757  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1758  * and result remains unchanged.
1759  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1760  * If in 'candidates' pool -1 value is considered as an empty value.
1761  * WARNING this method returns only ONE set of result !
1762  */
1763 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1764 {
1765   if(candidates.size()<1)
1766     return false;
1767   bool ret=false;
1768   std::vector<int>::const_iterator iter=candidates.begin();
1769   int start=(*iter++);
1770   for(;iter!=candidates.end();iter++)
1771     {
1772       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1773       if(status!=0)
1774         {
1775           if(!ret)
1776             {
1777               result->pushBackSilent(start);
1778               ret=true;
1779             }
1780           if(status==1)
1781             result->pushBackSilent(*iter);
1782           else
1783             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1784         }
1785     }
1786   return ret;
1787 }
1788
1789 /*!
1790  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1791  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1792  *
1793  * \param [in] compType input specifying the technique used to compare cells each other.
1794  *   - 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.
1795  *   - 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)
1796  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1797  *   - 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
1798  * can be used for users not sensitive to orientation of cell
1799  * \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.
1800  * \param [out] commonCells
1801  * \param [out] commonCellsI
1802  * \return the correspondance array old to new in a newly allocated array.
1803  * 
1804  */
1805 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1806 {
1807   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1808   getReverseNodalConnectivity(revNodal,revNodalI);
1809   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1810 }
1811
1812 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1813                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1814 {
1815   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1816   int nbOfCells=nodalI->getNumberOfTuples()-1;
1817   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1818   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1819   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1820   std::vector<bool> isFetched(nbOfCells,false);
1821   if(startCellId==0)
1822     {
1823       for(int i=0;i<nbOfCells;i++)
1824         {
1825           if(!isFetched[i])
1826             {
1827               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1828               std::vector<int> v,v2;
1829               if(connOfNode!=connPtr+connIPtr[i+1])
1830                 {
1831                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1832                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1833                   connOfNode++;
1834                 }
1835               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1836                 if(*connOfNode>=0)
1837                   {
1838                     v=v2;
1839                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1840                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1841                     v2.resize(std::distance(v2.begin(),it));
1842                   }
1843               if(v2.size()>1)
1844                 {
1845                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1846                     {
1847                       int pos=commonCellsI->back();
1848                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1849                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1850                         isFetched[*it]=true;
1851                     }
1852                 }
1853             }
1854         }
1855     }
1856   else
1857     {
1858       for(int i=startCellId;i<nbOfCells;i++)
1859         {
1860           if(!isFetched[i])
1861             {
1862               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1863               std::vector<int> v,v2;
1864               if(connOfNode!=connPtr+connIPtr[i+1])
1865                 {
1866                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1867                   connOfNode++;
1868                 }
1869               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1870                 if(*connOfNode>=0)
1871                   {
1872                     v=v2;
1873                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1874                     v2.resize(std::distance(v2.begin(),it));
1875                   }
1876               if(v2.size()>1)
1877                 {
1878                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1879                     {
1880                       int pos=commonCellsI->back();
1881                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1882                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1883                         isFetched[*it]=true;
1884                     }
1885                 }
1886             }
1887         }
1888     }
1889   commonCellsArr=commonCells.retn();
1890   commonCellsIArr=commonCellsI.retn();
1891 }
1892
1893 /*!
1894  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1895  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1896  * than \a other->getNumberOfCells() in the returned array means that there is no
1897  * corresponding cell in \a this mesh.
1898  * It is expected that \a this and \a other meshes share the same node coordinates
1899  * array, if it is not so an exception is thrown. 
1900  *  \param [in] other - the mesh to compare with.
1901  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1902  *         valid values [0,1,2], see zipConnectivityTraducer().
1903  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1904  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1905  *         values. The caller is to delete this array using
1906  *         decrRef() as it is no more needed.
1907  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1908  *         mesh.
1909  *
1910  *  \if ENABLE_EXAMPLES
1911  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1912  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1913  *  \endif
1914  *  \sa checkDeepEquivalOnSameNodesWith()
1915  *  \sa checkGeoEquivalWith()
1916  */
1917 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1918 {
1919   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1920   int nbOfCells=getNumberOfCells();
1921   static const int possibleCompType[]={0,1,2};
1922   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1923     {
1924       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1925       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1926       oss << " !";
1927       throw INTERP_KERNEL::Exception(oss.str().c_str());
1928     }
1929   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1930   arr=o2n->substr(nbOfCells);
1931   arr->setName(other->getName());
1932   int tmp;
1933   if(other->getNumberOfCells()==0)
1934     return true;
1935   return arr->getMaxValue(tmp)<nbOfCells;
1936 }
1937
1938 /*!
1939  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1940  * This method tries to determine if \b other is fully included in \b this.
1941  * The main difference is that this method is not expected to throw exception.
1942  * This method has two outputs :
1943  *
1944  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1945  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1946  */
1947 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1948 {
1949   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1950   DataArrayInt *commonCells=0,*commonCellsI=0;
1951   int thisNbCells=getNumberOfCells();
1952   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1953   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1954   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1955   int otherNbCells=other->getNumberOfCells();
1956   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1957   arr2->alloc(otherNbCells,1);
1958   arr2->fillWithZero();
1959   int *arr2Ptr=arr2->getPointer();
1960   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1961   for(int i=0;i<nbOfCommon;i++)
1962     {
1963       int start=commonCellsPtr[commonCellsIPtr[i]];
1964       if(start<thisNbCells)
1965         {
1966           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1967             {
1968               int sig=commonCellsPtr[j]>0?1:-1;
1969               int val=std::abs(commonCellsPtr[j])-1;
1970               if(val>=thisNbCells)
1971                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1972             }
1973         }
1974     }
1975   arr2->setName(other->getName());
1976   if(arr2->presenceOfValue(0))
1977     return false;
1978   arr=arr2.retn();
1979   return true;
1980 }
1981
1982 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1983 {
1984   if(!other)
1985     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1986   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1987   if(!otherC)
1988     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1989   std::vector<const MEDCouplingUMesh *> ms(2);
1990   ms[0]=this;
1991   ms[1]=otherC;
1992   return MergeUMeshesOnSameCoords(ms);
1993 }
1994
1995 /*!
1996  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1997  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1998  * cellIds is not given explicitely but by a range python like.
1999  * 
2000  * \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.
2001  * \return a newly allocated
2002  * 
2003  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2004  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2005  */
2006 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2007 {
2008   if(getMeshDimension()!=-1)
2009     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2010   else
2011     {
2012       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2013       if(newNbOfCells!=1)
2014         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2015       if(start!=0)
2016         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2017       incrRef();
2018       return const_cast<MEDCouplingUMesh *>(this);
2019     }
2020 }
2021
2022 /*!
2023  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2024  * The result mesh shares or not the node coordinates array with \a this mesh depending
2025  * on \a keepCoords parameter.
2026  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2027  *           to write this mesh to the MED file, its cells must be sorted using
2028  *           sortCellsInMEDFileFrmt().
2029  *  \param [in] begin - an array of cell ids to include to the new mesh.
2030  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2031  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2032  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2033  *         by calling zipCoords().
2034  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2035  *         to delete this mesh using decrRef() as it is no more needed. 
2036  *  \throw If the coordinates array is not set.
2037  *  \throw If the nodal connectivity of cells is not defined.
2038  *  \throw If any cell id in the array \a begin is not valid.
2039  *
2040  *  \if ENABLE_EXAMPLES
2041  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2042  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2043  *  \endif
2044  */
2045 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2046 {
2047   if(getMeshDimension()!=-1)
2048     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2049   else
2050     {
2051       if(end-begin!=1)
2052         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2053       if(begin[0]!=0)
2054         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2055       incrRef();
2056       return const_cast<MEDCouplingUMesh *>(this);
2057     }
2058 }
2059
2060 /*!
2061  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2062  *
2063  * 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.
2064  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2065  * The number of cells of \b this will remain the same with this method.
2066  *
2067  * \param [in] begin begin of cell ids (included) of cells in this to assign
2068  * \param [in] end end of cell ids (excluded) of cells in this to assign
2069  * \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 ).
2070  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2071  */
2072 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2073 {
2074   checkConnectivityFullyDefined();
2075   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2076   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2077     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2078   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2079     {
2080       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2081       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2082       throw INTERP_KERNEL::Exception(oss.str().c_str());
2083     }
2084   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2085   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2086     {
2087       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2088       throw INTERP_KERNEL::Exception(oss.str().c_str());
2089     }
2090   int nbOfCells=getNumberOfCells();
2091   bool easyAssign=true;
2092   const int *connI=_nodal_connec_index->getConstPointer();
2093   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2094   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2095     {
2096       if(*it>=0 && *it<nbOfCells)
2097         {
2098           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2099         }
2100       else
2101         {
2102           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2103           throw INTERP_KERNEL::Exception(oss.str().c_str());
2104         }
2105     }
2106   if(easyAssign)
2107     {
2108       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2109       computeTypes();
2110     }
2111   else
2112     {
2113       DataArrayInt *arrOut=0,*arrIOut=0;
2114       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2115                                                arrOut,arrIOut);
2116       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2117       setConnectivity(arrOut,arrIOut,true);
2118     }
2119 }
2120
2121 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2122 {
2123   checkConnectivityFullyDefined();
2124   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2125   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2126     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2127   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2128     {
2129       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2130       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2131       throw INTERP_KERNEL::Exception(oss.str().c_str());
2132     }
2133   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2134   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2135     {
2136       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2137       throw INTERP_KERNEL::Exception(oss.str().c_str());
2138     }
2139   int nbOfCells=getNumberOfCells();
2140   bool easyAssign=true;
2141   const int *connI=_nodal_connec_index->getConstPointer();
2142   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2143   int it=start;
2144   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2145     {
2146       if(it>=0 && it<nbOfCells)
2147         {
2148           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2149         }
2150       else
2151         {
2152           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2153           throw INTERP_KERNEL::Exception(oss.str().c_str());
2154         }
2155     }
2156   if(easyAssign)
2157     {
2158       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2159       computeTypes();
2160     }
2161   else
2162     {
2163       DataArrayInt *arrOut=0,*arrIOut=0;
2164       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2165                                                 arrOut,arrIOut);
2166       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2167       setConnectivity(arrOut,arrIOut,true);
2168     }
2169 }                      
2170
2171 /*!
2172  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2173  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2174  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2175  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2176  *
2177  * \param [in] begin input start of array of node ids.
2178  * \param [in] end input end of array of node ids.
2179  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2180  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2181  */
2182 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2183 {
2184   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2185   checkConnectivityFullyDefined();
2186   int tmp=-1;
2187   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2188   std::vector<bool> fastFinder(sz,false);
2189   for(const int *work=begin;work!=end;work++)
2190     if(*work>=0 && *work<sz)
2191       fastFinder[*work]=true;
2192   int nbOfCells=getNumberOfCells();
2193   const int *conn=getNodalConnectivity()->getConstPointer();
2194   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2195   for(int i=0;i<nbOfCells;i++)
2196     {
2197       int ref=0,nbOfHit=0;
2198       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2199         if(*work2>=0)
2200           {
2201             ref++;
2202             if(fastFinder[*work2])
2203               nbOfHit++;
2204           }
2205       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2206         cellIdsKept->pushBackSilent(i);
2207     }
2208   cellIdsKeptArr=cellIdsKept.retn();
2209 }
2210
2211 /*!
2212  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2213  * this->getMeshDimension(), that bound some cells of \a this mesh.
2214  * The cells of lower dimension to include to the result mesh are selected basing on
2215  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2216  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2217  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2218  * created mesh shares the node coordinates array with \a this mesh. 
2219  *  \param [in] begin - the array of node ids.
2220  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2221  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2222  *         array \a begin are added, else cells whose any node is in the
2223  *         array \a begin are added.
2224  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2225  *         to delete this mesh using decrRef() as it is no more needed. 
2226  *  \throw If the coordinates array is not set.
2227  *  \throw If the nodal connectivity of cells is not defined.
2228  *  \throw If any node id in \a begin is not valid.
2229  *
2230  *  \if ENABLE_EXAMPLES
2231  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2232  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2233  *  \endif
2234  */
2235 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2236 {
2237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2238   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2239   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2240   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2241   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2242 }
2243
2244 /*!
2245  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2246  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2247  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2248  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2249  *         by calling zipCoords().
2250  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2251  *         to delete this mesh using decrRef() as it is no more needed. 
2252  *  \throw If the coordinates array is not set.
2253  *  \throw If the nodal connectivity of cells is not defined.
2254  *
2255  *  \if ENABLE_EXAMPLES
2256  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2257  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2258  *  \endif
2259  */
2260 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2261 {
2262   DataArrayInt *desc=DataArrayInt::New();
2263   DataArrayInt *descIndx=DataArrayInt::New();
2264   DataArrayInt *revDesc=DataArrayInt::New();
2265   DataArrayInt *revDescIndx=DataArrayInt::New();
2266   //
2267   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2268   revDesc->decrRef();
2269   desc->decrRef();
2270   descIndx->decrRef();
2271   int nbOfCells=meshDM1->getNumberOfCells();
2272   const int *revDescIndxC=revDescIndx->getConstPointer();
2273   std::vector<int> boundaryCells;
2274   for(int i=0;i<nbOfCells;i++)
2275     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2276       boundaryCells.push_back(i);
2277   revDescIndx->decrRef();
2278   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2279   return ret;
2280 }
2281
2282 /*!
2283  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2284  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2285  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2286  */
2287 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2288 {
2289   checkFullyDefined();
2290   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2291   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2292   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2293   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2294   //
2295   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2296   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2297   //
2298   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2299   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2300   const int *revDescPtr=revDesc->getConstPointer();
2301   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2302   int nbOfCells=getNumberOfCells();
2303   std::vector<bool> ret1(nbOfCells,false);
2304   int sz=0;
2305   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2306     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2307       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2308   //
2309   DataArrayInt *ret2=DataArrayInt::New();
2310   ret2->alloc(sz,1);
2311   int *ret2Ptr=ret2->getPointer();
2312   sz=0;
2313   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2314     if(*it)
2315       *ret2Ptr++=sz;
2316   ret2->setName("BoundaryCells");
2317   return ret2;
2318 }
2319
2320 /*!
2321  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2322  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2323  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2324  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2325  *
2326  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2327  * This method method returns cells ids set s = s1 + s2 where :
2328  * 
2329  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2330  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2331  *
2332  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2333  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2334  *
2335  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2336  * \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
2337  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2338  */
2339 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2340 {
2341   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2342     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2343   checkConnectivityFullyDefined();
2344   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2345   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2346     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2347   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2348   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2349   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2350   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2351   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2352   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2353   DataArrayInt *idsOtherInConsti=0;
2354   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2355   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2356   if(!b)
2357     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2358   std::set<int> s1;
2359   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2360     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2361   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2362   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2363   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2364   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2365   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2366   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2367   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2368   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2369   neighThisPartAuto=0;
2370   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2371   const int li[2]={0,1};
2372   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2373   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2374   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2375   s_renum1->sort();
2376   //
2377   cellIdsRk0=s0arr.retn();
2378   cellIdsRk1=s_renum1.retn();
2379 }
2380
2381 /*!
2382  * 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
2383  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2384  * 
2385  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2386  */
2387 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2388 {
2389   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2392   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2393   //
2394   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2395   revDesc=0; desc=0; descIndx=0;
2396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2397   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2398   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2399 }
2400
2401 /*!
2402  * Finds nodes lying on the boundary of \a this mesh.
2403  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2404  *          nodes. The caller is to delete this array using decrRef() as it is no
2405  *          more needed.
2406  *  \throw If the coordinates array is not set.
2407  *  \throw If the nodal connectivity of cells is node defined.
2408  *
2409  *  \if ENABLE_EXAMPLES
2410  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2411  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2412  *  \endif
2413  */
2414 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2415 {
2416   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2417   return skin->computeFetchedNodeIds();
2418 }
2419
2420 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2421 {
2422   incrRef();
2423   return const_cast<MEDCouplingUMesh *>(this);
2424 }
2425
2426 /*!
2427  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2428  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2429  * 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.
2430  * 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.
2431  * 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.
2432  *
2433  * \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
2434  *             parameter is altered during the call.
2435  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2436  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2437  * \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.
2438  *
2439  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2440  */
2441 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2442                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2443 {
2444   checkFullyDefined();
2445   otherDimM1OnSameCoords.checkFullyDefined();
2446   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2447     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2448   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2449     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2450   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2451   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2452   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2453   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2454   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2455   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2456   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2457   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2458   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2459   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2460   //
2461   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2462   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2463   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2464   DataArrayInt *idsTmp=0;
2465   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2466   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2467   if(!b)
2468     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2469   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2470   DataArrayInt *tmp0=0,*tmp1=0;
2471   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2472   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2473   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2474   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2475   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2476   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2477   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2478   //
2479   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2480   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2481   nodeIdsToDuplicate=s3.retn();
2482 }
2483
2484 /*!
2485  * This method operates a modification of the connectivity and coords in \b this.
2486  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2487  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2488  * 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
2489  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2490  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2491  * 
2492  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2493  * 
2494  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2495  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2496  */
2497 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2498 {
2499   int nbOfNodes=getNumberOfNodes();
2500   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2501   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2502 }
2503
2504 /*!
2505  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2506  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2507  * This method is a generalization of shiftNodeNumbersInConn().
2508  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2509  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2510  *         this->getNumberOfNodes(), in "Old to New" mode. 
2511  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2512  *  \throw If the nodal connectivity of cells is not defined.
2513  *
2514  *  \if ENABLE_EXAMPLES
2515  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2516  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2517  *  \endif
2518  */
2519 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2520 {
2521   checkConnectivityFullyDefined();
2522   int *conn=getNodalConnectivity()->getPointer();
2523   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2524   int nbOfCells=getNumberOfCells();
2525   for(int i=0;i<nbOfCells;i++)
2526     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2527       {
2528         int& node=conn[iconn];
2529         if(node>=0)//avoid polyhedron separator
2530           {
2531             node=newNodeNumbersO2N[node];
2532           }
2533       }
2534   _nodal_connec->declareAsNew();
2535   updateTime();
2536 }
2537
2538 /*!
2539  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2540  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2541  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2542  * 
2543  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2544  */
2545 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2546 {
2547   checkConnectivityFullyDefined();
2548   int *conn=getNodalConnectivity()->getPointer();
2549   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2550   int nbOfCells=getNumberOfCells();
2551   for(int i=0;i<nbOfCells;i++)
2552     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2553       {
2554         int& node=conn[iconn];
2555         if(node>=0)//avoid polyhedron separator
2556           {
2557             node+=delta;
2558           }
2559       }
2560   _nodal_connec->declareAsNew();
2561   updateTime();
2562 }
2563
2564 /*!
2565  * This method operates a modification of the connectivity in \b this.
2566  * 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.
2567  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2568  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2569  * 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
2570  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2571  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2572  * 
2573  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2574  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2575  * 
2576  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2577  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2578  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2579  */
2580 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2581 {
2582   checkConnectivityFullyDefined();
2583   std::map<int,int> m;
2584   int val=offset;
2585   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2586     m[*work]=val;
2587   int *conn=getNodalConnectivity()->getPointer();
2588   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2589   int nbOfCells=getNumberOfCells();
2590   for(int i=0;i<nbOfCells;i++)
2591     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2592       {
2593         int& node=conn[iconn];
2594         if(node>=0)//avoid polyhedron separator
2595           {
2596             std::map<int,int>::iterator it=m.find(node);
2597             if(it!=m.end())
2598               node=(*it).second;
2599           }
2600       }
2601   updateTime();
2602 }
2603
2604 /*!
2605  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2606  *
2607  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2608  * After the call of this method the number of cells remains the same as before.
2609  *
2610  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2611  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2612  * be strictly in [0;this->getNumberOfCells()).
2613  *
2614  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2615  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2616  * should be contained in[0;this->getNumberOfCells()).
2617  * 
2618  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2619  */
2620 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2621 {
2622   checkConnectivityFullyDefined();
2623   int nbCells=getNumberOfCells();
2624   const int *array=old2NewBg;
2625   if(check)
2626     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2627   //
2628   const int *conn=_nodal_connec->getConstPointer();
2629   const int *connI=_nodal_connec_index->getConstPointer();
2630   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2631   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2632   const int *n2oPtr=n2o->begin();
2633   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2634   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2635   newConn->copyStringInfoFrom(*_nodal_connec);
2636   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2637   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2638   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2639   //
2640   int *newC=newConn->getPointer();
2641   int *newCI=newConnI->getPointer();
2642   int loc=0;
2643   newCI[0]=loc;
2644   for(int i=0;i<nbCells;i++)
2645     {
2646       int pos=n2oPtr[i];
2647       int nbOfElts=connI[pos+1]-connI[pos];
2648       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2649       loc+=nbOfElts;
2650       newCI[i+1]=loc;
2651     }
2652   //
2653   setConnectivity(newConn,newConnI);
2654   if(check)
2655     free(const_cast<int *>(array));
2656 }
2657
2658 /*!
2659  * Finds cells whose bounding boxes intersect a given bounding box.
2660  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2661  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2662  *         zMax (if in 3D). 
2663  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2664  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2665  *         extent of the bounding box of cell to produce an addition to this bounding box.
2666  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2667  *         cells. The caller is to delete this array using decrRef() as it is no more
2668  *         needed. 
2669  *  \throw If the coordinates array is not set.
2670  *  \throw If the nodal connectivity of cells is not defined.
2671  *
2672  *  \if ENABLE_EXAMPLES
2673  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2674  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2675  *  \endif
2676  */
2677 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2678 {
2679   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2680   if(getMeshDimension()==-1)
2681     {
2682       elems->pushBackSilent(0);
2683       return elems.retn();
2684     }
2685   int dim=getSpaceDimension();
2686   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2687   const int* conn      = getNodalConnectivity()->getConstPointer();
2688   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2689   const double* coords = getCoords()->getConstPointer();
2690   int nbOfCells=getNumberOfCells();
2691   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2692     {
2693       for (int i=0; i<dim; i++)
2694         {
2695           elem_bb[i*2]=std::numeric_limits<double>::max();
2696           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2697         }
2698
2699       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2700         {
2701           int node= conn[inode];
2702           if(node>=0)//avoid polyhedron separator
2703             {
2704               for (int idim=0; idim<dim; idim++)
2705                 {
2706                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2707                     {
2708                       elem_bb[idim*2] = coords[node*dim+idim] ;
2709                     }
2710                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2711                     {
2712                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2713                     }
2714                 }
2715             }
2716         }
2717       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2718         elems->pushBackSilent(ielem);
2719     }
2720   return elems.retn();
2721 }
2722
2723 /*!
2724  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2725  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2726  * added in 'elems' parameter.
2727  */
2728 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2729 {
2730   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2731   if(getMeshDimension()==-1)
2732     {
2733       elems->pushBackSilent(0);
2734       return elems.retn();
2735     }
2736   int dim=getSpaceDimension();
2737   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2738   const int* conn      = getNodalConnectivity()->getConstPointer();
2739   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2740   const double* coords = getCoords()->getConstPointer();
2741   int nbOfCells=getNumberOfCells();
2742   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2743     {
2744       for (int i=0; i<dim; i++)
2745         {
2746           elem_bb[i*2]=std::numeric_limits<double>::max();
2747           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2748         }
2749
2750       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2751         {
2752           int node= conn[inode];
2753           if(node>=0)//avoid polyhedron separator
2754             {
2755               for (int idim=0; idim<dim; idim++)
2756                 {
2757                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2758                     {
2759                       elem_bb[idim*2] = coords[node*dim+idim] ;
2760                     }
2761                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2762                     {
2763                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2764                     }
2765                 }
2766             }
2767         }
2768       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2769         elems->pushBackSilent(ielem);
2770     }
2771   return elems.retn();
2772 }
2773
2774 /*!
2775  * Returns a type of a cell by its id.
2776  *  \param [in] cellId - the id of the cell of interest.
2777  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2778  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2779  */
2780 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2781 {
2782   const int *ptI=_nodal_connec_index->getConstPointer();
2783   const int *pt=_nodal_connec->getConstPointer();
2784   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2785     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2786   else
2787     {
2788       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2789       throw INTERP_KERNEL::Exception(oss.str().c_str());
2790     }
2791 }
2792
2793 /*!
2794  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2795  * This method does not throw exception if geometric type \a type is not in \a this.
2796  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2797  * The coordinates array is not considered here.
2798  *
2799  * \param [in] type the geometric type
2800  * \return cell ids in this having geometric type \a type.
2801  */
2802 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2803 {
2804
2805   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2806   ret->alloc(0,1);
2807   checkConnectivityFullyDefined();
2808   int nbCells=getNumberOfCells();
2809   int mdim=getMeshDimension();
2810   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2811   if(mdim!=(int)cm.getDimension())
2812     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2813   const int *ptI=_nodal_connec_index->getConstPointer();
2814   const int *pt=_nodal_connec->getConstPointer();
2815   for(int i=0;i<nbCells;i++)
2816     {
2817       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2818         ret->pushBackSilent(i);
2819     }
2820   return ret.retn();
2821 }
2822
2823 /*!
2824  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2825  */
2826 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2827 {
2828   const int *ptI=_nodal_connec_index->getConstPointer();
2829   const int *pt=_nodal_connec->getConstPointer();
2830   int nbOfCells=getNumberOfCells();
2831   int ret=0;
2832   for(int i=0;i<nbOfCells;i++)
2833     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2834       ret++;
2835   return ret;
2836 }
2837
2838 /*!
2839  * Returns the nodal connectivity of a given cell.
2840  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2841  * all returned node ids can be used in getCoordinatesOfNode().
2842  *  \param [in] cellId - an id of the cell of interest.
2843  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2844  *         cleared before the appending.
2845  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2846  */
2847 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2848 {
2849   const int *ptI=_nodal_connec_index->getConstPointer();
2850   const int *pt=_nodal_connec->getConstPointer();
2851   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2852     if(*w>=0)
2853       conn.push_back(*w);
2854 }
2855
2856 std::string MEDCouplingUMesh::simpleRepr() const
2857 {
2858   static const char msg0[]="No coordinates specified !";
2859   std::ostringstream ret;
2860   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2861   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2862   int tmpp1,tmpp2;
2863   double tt=getTime(tmpp1,tmpp2);
2864   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2865   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2866   if(_mesh_dim>=-1)
2867     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2868   else
2869     { ret << " Mesh dimension has not been set or is invalid !"; }
2870   if(_coords!=0)
2871     {
2872       const int spaceDim=getSpaceDimension();
2873       ret << spaceDim << "\nInfo attached on space dimension : ";
2874       for(int i=0;i<spaceDim;i++)
2875         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2876       ret << "\n";
2877     }
2878   else
2879     ret << msg0 << "\n";
2880   ret << "Number of nodes : ";
2881   if(_coords!=0)
2882     ret << getNumberOfNodes() << "\n";
2883   else
2884     ret << msg0 << "\n";
2885   ret << "Number of cells : ";
2886   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2887     ret << getNumberOfCells() << "\n";
2888   else
2889     ret << "No connectivity specified !" << "\n";
2890   ret << "Cell types present : ";
2891   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2892     {
2893       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2894       ret << cm.getRepr() << " ";
2895     }
2896   ret << "\n";
2897   return ret.str();
2898 }
2899
2900 std::string MEDCouplingUMesh::advancedRepr() const
2901 {
2902   std::ostringstream ret;
2903   ret << simpleRepr();
2904   ret << "\nCoordinates array : \n___________________\n\n";
2905   if(_coords)
2906     _coords->reprWithoutNameStream(ret);
2907   else
2908     ret << "No array set !\n";
2909   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2910   reprConnectivityOfThisLL(ret);
2911   return ret.str();
2912 }
2913
2914 /*!
2915  * This method returns a C++ code that is a dump of \a this.
2916  * This method will throw if this is not fully defined.
2917  */
2918 std::string MEDCouplingUMesh::cppRepr() const
2919 {
2920   static const char coordsName[]="coords";
2921   static const char connName[]="conn";
2922   static const char connIName[]="connI";
2923   checkFullyDefined();
2924   std::ostringstream ret; ret << "// coordinates" << std::endl;
2925   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2926   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2927   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2928   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2929   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2930   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2931   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2932   return ret.str();
2933 }
2934
2935 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2936 {
2937   std::ostringstream ret;
2938   reprConnectivityOfThisLL(ret);
2939   return ret.str();
2940 }
2941
2942 /*!
2943  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2944  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2945  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2946  * some algos).
2947  * 
2948  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2949  * 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
2950  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2951  */
2952 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2953 {
2954   int mdim=getMeshDimension();
2955   if(mdim<0)
2956     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2957   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2958   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2959   bool needToCpyCT=true;
2960   if(!_nodal_connec)
2961     {
2962       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2963       needToCpyCT=false;
2964     }
2965   else
2966     {
2967       tmp1=_nodal_connec;
2968       tmp1->incrRef();
2969     }
2970   if(!_nodal_connec_index)
2971     {
2972       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2973       needToCpyCT=false;
2974     }
2975   else
2976     {
2977       tmp2=_nodal_connec_index;
2978       tmp2->incrRef();
2979     }
2980   ret->setConnectivity(tmp1,tmp2,false);
2981   if(needToCpyCT)
2982     ret->_types=_types;
2983   if(!_coords)
2984     {
2985       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2986       ret->setCoords(coords);
2987     }
2988   else
2989     ret->setCoords(_coords);
2990   return ret.retn();
2991 }
2992
2993 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2994 {
2995   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2996     {
2997       int nbOfCells=getNumberOfCells();
2998       const int *c=_nodal_connec->getConstPointer();
2999       const int *ci=_nodal_connec_index->getConstPointer();
3000       for(int i=0;i<nbOfCells;i++)
3001         {
3002           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3003           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3004           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3005           stream << "\n";
3006         }
3007     }
3008   else
3009     stream << "Connectivity not defined !\n";
3010 }
3011
3012 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3013 {
3014   const int *ptI=_nodal_connec_index->getConstPointer();
3015   const int *pt=_nodal_connec->getConstPointer();
3016   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3017     return ptI[cellId+1]-ptI[cellId]-1;
3018   else
3019     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3020 }
3021
3022 /*!
3023  * Returns types of cells of the specified part of \a this mesh.
3024  * This method avoids computing sub-mesh explicitely to get its types.
3025  *  \param [in] begin - an array of cell ids of interest.
3026  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3027  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3028  *         describing the cell types. 
3029  *  \throw If the coordinates array is not set.
3030  *  \throw If the nodal connectivity of cells is not defined.
3031  *  \sa getAllGeoTypes()
3032  */
3033 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3034 {
3035   checkFullyDefined();
3036   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3037   const int *conn=_nodal_connec->getConstPointer();
3038   const int *connIndex=_nodal_connec_index->getConstPointer();
3039   for(const int *w=begin;w!=end;w++)
3040     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3041   return ret;
3042 }
3043
3044 /*!
3045  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3046  * a set of types of cells constituting \a this mesh. 
3047  * This method is for advanced users having prepared their connectivity before. For
3048  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3049  *  \param [in] conn - the nodal connectivity array. 
3050  *  \param [in] connIndex - the nodal connectivity index array.
3051  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3052  *         mesh is updated.
3053  */
3054 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3055 {
3056   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3057   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3058   if(isComputingTypes)
3059     computeTypes();
3060   declareAsNew();
3061 }
3062
3063 /*!
3064  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3065  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3066  */
3067 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3068     _nodal_connec(0),_nodal_connec_index(0),
3069     _types(other._types)
3070 {
3071   if(other._nodal_connec)
3072     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3073   if(other._nodal_connec_index)
3074     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3075 }
3076
3077 MEDCouplingUMesh::~MEDCouplingUMesh()
3078 {
3079   if(_nodal_connec)
3080     _nodal_connec->decrRef();
3081   if(_nodal_connec_index)
3082     _nodal_connec_index->decrRef();
3083 }
3084
3085 /*!
3086  * Recomputes a set of cell types of \a this mesh. For more info see
3087  * \ref MEDCouplingUMeshNodalConnectivity.
3088  */
3089 void MEDCouplingUMesh::computeTypes()
3090 {
3091   if(_nodal_connec && _nodal_connec_index)
3092     {
3093       _types.clear();
3094       const int *conn=_nodal_connec->getConstPointer();
3095       const int *connIndex=_nodal_connec_index->getConstPointer();
3096       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3097       if (nbOfElem > 0)
3098         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3099           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3100     }
3101 }
3102
3103 /*!
3104  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3105  */
3106 void MEDCouplingUMesh::checkFullyDefined() const
3107 {
3108   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3109     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3110 }
3111
3112 /*!
3113  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3114  */
3115 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3116 {
3117   if(!_nodal_connec_index || !_nodal_connec)
3118     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3119 }
3120
3121 /*!
3122  * Returns a number of cells constituting \a this mesh. 
3123  *  \return int - the number of cells in \a this mesh.
3124  *  \throw If the nodal connectivity of cells is not defined.
3125  */
3126 int MEDCouplingUMesh::getNumberOfCells() const
3127
3128   if(_nodal_connec_index)
3129     return _nodal_connec_index->getNumberOfTuples()-1;
3130   else
3131     if(_mesh_dim==-1)
3132       return 1;
3133     else
3134       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3135 }
3136
3137 /*!
3138  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3139  * mesh. For more info see \ref MEDCouplingMeshesPage.
3140  *  \return int - the dimension of \a this mesh.
3141  *  \throw If the mesh dimension is not defined using setMeshDimension().
3142  */
3143 int MEDCouplingUMesh::getMeshDimension() const
3144 {
3145   if(_mesh_dim<-1)
3146     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3147   return _mesh_dim;
3148 }
3149
3150 /*!
3151  * Returns a length of the nodal connectivity array.
3152  * This method is for test reason. Normally the integer returned is not useable by
3153  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3154  *  \return int - the length of the nodal connectivity array.
3155  */
3156 int MEDCouplingUMesh::getMeshLength() const
3157 {
3158   return _nodal_connec->getNbOfElems();
3159 }
3160
3161 /*!
3162  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3163  */
3164 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3165 {
3166   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3167   tinyInfo.push_back(getMeshDimension());
3168   tinyInfo.push_back(getNumberOfCells());
3169   if(_nodal_connec)
3170     tinyInfo.push_back(getMeshLength());
3171   else
3172     tinyInfo.push_back(-1);
3173 }
3174
3175 /*!
3176  * First step of unserialization process.
3177  */
3178 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3179 {
3180   return tinyInfo[6]<=0;
3181 }
3182
3183 /*!
3184  * Second step of serialization process.
3185  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3186  */
3187 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3188 {
3189   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3190   if(tinyInfo[5]!=-1)
3191     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3192 }
3193
3194 /*!
3195  * Third and final step of serialization process.
3196  */
3197 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3198 {
3199   MEDCouplingPointSet::serialize(a1,a2);
3200   if(getMeshDimension()>-1)
3201     {
3202       a1=DataArrayInt::New();
3203       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3204       int *ptA1=a1->getPointer();
3205       const int *conn=getNodalConnectivity()->getConstPointer();
3206       const int *index=getNodalConnectivityIndex()->getConstPointer();
3207       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3208       std::copy(conn,conn+getMeshLength(),ptA1);
3209     }
3210   else
3211     a1=0;
3212 }
3213
3214 /*!
3215  * Second and final unserialization process.
3216  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3217  */
3218 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3219 {
3220   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3221   setMeshDimension(tinyInfo[5]);
3222   if(tinyInfo[7]!=-1)
3223     {
3224       // Connectivity
3225       const int *recvBuffer=a1->getConstPointer();
3226       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3227       myConnecIndex->alloc(tinyInfo[6]+1,1);
3228       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3229       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3230       myConnec->alloc(tinyInfo[7],1);
3231       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3232       setConnectivity(myConnec, myConnecIndex);
3233     }
3234 }
3235
3236 /*!
3237  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3238  * CellIds are given using range specified by a start an end and step.
3239  */
3240 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3241 {
3242   checkFullyDefined();
3243   int ncell=getNumberOfCells();
3244   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3245   ret->_mesh_dim=_mesh_dim;
3246   ret->setCoords(_coords);
3247   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3248   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3249   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3250   int work=start;
3251   const int *conn=_nodal_connec->getConstPointer();
3252   const int *connIndex=_nodal_connec_index->getConstPointer();
3253   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3254     {
3255       if(work>=0 && work<ncell)
3256         {
3257           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3258         }
3259       else
3260         {
3261           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3262           throw INTERP_KERNEL::Exception(oss.str().c_str());
3263         }
3264     }
3265   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3266   int *newConnPtr=newConn->getPointer();
3267   std::set<INTERP_KERNEL::NormalizedCellType> types;
3268   work=start;
3269   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3270     {
3271       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3272       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3273     }
3274   ret->setConnectivity(newConn,newConnI,false);
3275   ret->_types=types;
3276   ret->copyTinyInfoFrom(this);
3277   return ret.retn();
3278 }
3279
3280 /*!
3281  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3282  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3283  * The return newly allocated mesh will share the same coordinates as \a this.
3284  */
3285 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3286 {
3287   checkConnectivityFullyDefined();
3288   int ncell=getNumberOfCells();
3289   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3290   ret->_mesh_dim=_mesh_dim;
3291   ret->setCoords(_coords);
3292   std::size_t nbOfElemsRet=std::distance(begin,end);
3293   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3294   connIndexRet[0]=0;
3295   const int *conn=_nodal_connec->getConstPointer();
3296   const int *connIndex=_nodal_connec_index->getConstPointer();
3297   int newNbring=0;
3298   for(const int *work=begin;work!=end;work++,newNbring++)
3299     {
3300       if(*work>=0 && *work<ncell)
3301         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3302       else
3303         {
3304           free(connIndexRet);
3305           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3306           throw INTERP_KERNEL::Exception(oss.str().c_str());
3307         }
3308     }
3309   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3310   int *connRetWork=connRet;
3311   std::set<INTERP_KERNEL::NormalizedCellType> types;
3312   for(const int *work=begin;work!=end;work++)
3313     {
3314       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3315       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3316     }
3317   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3318   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3320   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3321   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3322   ret->_types=types;
3323   ret->copyTinyInfoFrom(this);
3324   return ret.retn();
3325 }
3326
3327 /*!
3328  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3329  * mesh.<br>
3330  * For 1D cells, the returned field contains lengths.<br>
3331  * For 2D cells, the returned field contains areas.<br>
3332  * For 3D cells, the returned field contains volumes.
3333  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3334  *         orientation, i.e. the volume is always positive.
3335  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3336  *         and one time . The caller is to delete this field using decrRef() as it is no
3337  *         more needed.
3338  */
3339 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3340 {
3341   std::string name="MeasureOfMesh_";
3342   name+=getName();
3343   int nbelem=getNumberOfCells();
3344   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3345   field->setName(name);
3346   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3347   array->alloc(nbelem,1);
3348   double *area_vol=array->getPointer();
3349   field->setArray(array) ; array=0;
3350   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3351   field->synchronizeTimeWithMesh();
3352   if(getMeshDimension()!=-1)
3353     {
3354       int ipt;
3355       INTERP_KERNEL::NormalizedCellType type;
3356       int dim_space=getSpaceDimension();
3357       const double *coords=getCoords()->getConstPointer();
3358       const int *connec=getNodalConnectivity()->getConstPointer();
3359       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3360       for(int iel=0;iel<nbelem;iel++)
3361         {
3362           ipt=connec_index[iel];
3363           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3364           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);
3365         }
3366       if(isAbs)
3367         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3368     }
3369   else
3370     {
3371       area_vol[0]=std::numeric_limits<double>::max();
3372     }
3373   return field.retn();
3374 }
3375
3376 /*!
3377  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3378  * mesh.<br>
3379  * For 1D cells, the returned array contains lengths.<br>
3380  * For 2D cells, the returned array contains areas.<br>
3381  * For 3D cells, the returned array contains volumes.
3382  * This method avoids building explicitly a part of \a this mesh to perform the work.
3383  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3384  *         orientation, i.e. the volume is always positive.
3385  *  \param [in] begin - an array of cell ids of interest.
3386  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3387  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3388  *          delete this array using decrRef() as it is no more needed.
3389  * 
3390  *  \if ENABLE_EXAMPLES
3391  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3392  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3393  *  \endif
3394  *  \sa getMeasureField()
3395  */
3396 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3397 {
3398   std::string name="PartMeasureOfMesh_";
3399   name+=getName();
3400   int nbelem=(int)std::distance(begin,end);
3401   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3402   array->setName(name);
3403   array->alloc(nbelem,1);
3404   double *area_vol=array->getPointer();
3405   if(getMeshDimension()!=-1)
3406     {
3407       int ipt;
3408       INTERP_KERNEL::NormalizedCellType type;
3409       int dim_space=getSpaceDimension();
3410       const double *coords=getCoords()->getConstPointer();
3411       const int *connec=getNodalConnectivity()->getConstPointer();
3412       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3413       for(const int *iel=begin;iel!=end;iel++)
3414         {
3415           ipt=connec_index[*iel];
3416           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3417           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3418         }
3419       if(isAbs)
3420         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3421     }
3422   else
3423     {
3424       area_vol[0]=std::numeric_limits<double>::max();
3425     }
3426   return array.retn();
3427 }
3428
3429 /*!
3430  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3431  * \a this one. The returned field contains the dual cell volume for each corresponding
3432  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3433  *  the dual mesh in P1 sens of \a this.<br>
3434  * For 1D cells, the returned field contains lengths.<br>
3435  * For 2D cells, the returned field contains areas.<br>
3436  * For 3D cells, the returned field contains volumes.
3437  * This method is useful to check "P1*" conservative interpolators.
3438  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3439  *         orientation, i.e. the volume is always positive.
3440  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3441  *          nodes and one time. The caller is to delete this array using decrRef() as
3442  *          it is no more needed.
3443  */
3444 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3445 {
3446   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3447   std::string name="MeasureOnNodeOfMesh_";
3448   name+=getName();
3449   int nbNodes=getNumberOfNodes();
3450   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3451   double cst=1./((double)getMeshDimension()+1.);
3452   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3453   array->alloc(nbNodes,1);
3454   double *valsToFill=array->getPointer();
3455   std::fill(valsToFill,valsToFill+nbNodes,0.);
3456   const double *values=tmp->getArray()->getConstPointer();
3457   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3458   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3459   getReverseNodalConnectivity(da,daInd);
3460   const int *daPtr=da->getConstPointer();
3461   const int *daIPtr=daInd->getConstPointer();
3462   for(int i=0;i<nbNodes;i++)
3463     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3464       valsToFill[i]+=cst*values[*cell];
3465   ret->setMesh(this);
3466   ret->setArray(array);
3467   return ret.retn();
3468 }
3469
3470 /*!
3471  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3472  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3473  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3474  * and are normalized.
3475  * <br> \a this can be either 
3476  * - a  2D mesh in 2D or 3D space or 
3477  * - an 1D mesh in 2D space.
3478  * 
3479  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3480  *          cells and one time. The caller is to delete this field using decrRef() as
3481  *          it is no more needed.
3482  *  \throw If the nodal connectivity of cells is not defined.
3483  *  \throw If the coordinates array is not set.
3484  *  \throw If the mesh dimension is not set.
3485  *  \throw If the mesh and space dimension is not as specified above.
3486  */
3487 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3488 {
3489   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3490     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3491   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3492   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3493   int nbOfCells=getNumberOfCells();
3494   int nbComp=getMeshDimension()+1;
3495   array->alloc(nbOfCells,nbComp);
3496   double *vals=array->getPointer();
3497   const int *connI=_nodal_connec_index->getConstPointer();
3498   const int *conn=_nodal_connec->getConstPointer();
3499   const double *coords=_coords->getConstPointer();
3500   if(getMeshDimension()==2)
3501     {
3502       if(getSpaceDimension()==3)
3503         {
3504           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3505           const double *locPtr=loc->getConstPointer();
3506           for(int i=0;i<nbOfCells;i++,vals+=3)
3507             {
3508               int offset=connI[i];
3509               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3510               double n=INTERP_KERNEL::norm<3>(vals);
3511               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3512             }
3513         }
3514       else
3515         {
3516           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3517           const double *isAbsPtr=isAbs->getArray()->begin();
3518           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3519             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3520         }
3521     }
3522   else//meshdimension==1
3523     {
3524       double tmp[2];
3525       for(int i=0;i<nbOfCells;i++)
3526         {
3527           int offset=connI[i];
3528           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3529           double n=INTERP_KERNEL::norm<2>(tmp);
3530           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3531           *vals++=-tmp[1];
3532           *vals++=tmp[0];
3533         }
3534     }
3535   ret->setArray(array);
3536   ret->setMesh(this);
3537   ret->synchronizeTimeWithSupport();
3538   return ret.retn();
3539 }
3540
3541 /*!
3542  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3543  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3544  * and are normalized.
3545  * <br> \a this can be either 
3546  * - a  2D mesh in 2D or 3D space or 
3547  * - an 1D mesh in 2D space.
3548  * 
3549  * This method avoids building explicitly a part of \a this mesh to perform the work.
3550  *  \param [in] begin - an array of cell ids of interest.
3551  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3552  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3553  *          cells and one time. The caller is to delete this field using decrRef() as
3554  *          it is no more needed.
3555  *  \throw If the nodal connectivity of cells is not defined.
3556  *  \throw If the coordinates array is not set.
3557  *  \throw If the mesh dimension is not set.
3558  *  \throw If the mesh and space dimension is not as specified above.
3559  *  \sa buildOrthogonalField()
3560  *
3561  *  \if ENABLE_EXAMPLES
3562  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3563  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3564  *  \endif
3565  */
3566 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3567 {
3568   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3569     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3570   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3571   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3572   std::size_t nbelems=std::distance(begin,end);
3573   int nbComp=getMeshDimension()+1;
3574   array->alloc((int)nbelems,nbComp);
3575   double *vals=array->getPointer();
3576   const int *connI=_nodal_connec_index->getConstPointer();
3577   const int *conn=_nodal_connec->getConstPointer();
3578   const double *coords=_coords->getConstPointer();
3579   if(getMeshDimension()==2)
3580     {
3581       if(getSpaceDimension()==3)
3582         {
3583           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3584           const double *locPtr=loc->getConstPointer();
3585           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3586             {
3587               int offset=connI[*i];
3588               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3589               double n=INTERP_KERNEL::norm<3>(vals);
3590               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3591             }
3592         }
3593       else
3594         {
3595           for(std::size_t i=0;i<nbelems;i++)
3596             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3597         }
3598     }
3599   else//meshdimension==1
3600     {
3601       double tmp[2];
3602       for(const int *i=begin;i!=end;i++)
3603         {
3604           int offset=connI[*i];
3605           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3606           double n=INTERP_KERNEL::norm<2>(tmp);
3607           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3608           *vals++=-tmp[1];
3609           *vals++=tmp[0];
3610         }
3611     }
3612   ret->setArray(array);
3613   ret->setMesh(this);
3614   ret->synchronizeTimeWithSupport();
3615   return ret.retn();
3616 }
3617
3618 /*!
3619  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3620  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3621  * and are \b not normalized.
3622  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3623  *          cells and one time. The caller is to delete this field using decrRef() as
3624  *          it is no more needed.
3625  *  \throw If the nodal connectivity of cells is not defined.
3626  *  \throw If the coordinates array is not set.
3627  *  \throw If \a this->getMeshDimension() != 1.
3628  *  \throw If \a this mesh includes cells of type other than SEG2.
3629  */
3630 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3631 {
3632   if(getMeshDimension()!=1)
3633     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3634   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3635     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3636   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3637   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3638   int nbOfCells=getNumberOfCells();
3639   int spaceDim=getSpaceDimension();
3640   array->alloc(nbOfCells,spaceDim);
3641   double *pt=array->getPointer();
3642   const double *coo=getCoords()->getConstPointer();
3643   std::vector<int> conn;
3644   conn.reserve(2);
3645   for(int i=0;i<nbOfCells;i++)
3646     {
3647       conn.resize(0);
3648       getNodeIdsOfCell(i,conn);
3649       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3650     }
3651   ret->setArray(array);
3652   ret->setMesh(this);
3653   ret->synchronizeTimeWithSupport();
3654   return ret.retn();
3655 }
3656
3657 /*!
3658  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3659  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3660  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3661  * from. If a result face is shared by two 3D cells, then the face in included twice in
3662  * the result mesh.
3663  *  \param [in] origin - 3 components of a point defining location of the plane.
3664  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3665  *         must be greater than 1e-6.
3666  *  \param [in] eps - half-thickness of the plane.
3667  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3668  *         producing correspondent 2D cells. The caller is to delete this array
3669  *         using decrRef() as it is no more needed.
3670  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3671  *         not share the node coordinates array with \a this mesh. The caller is to
3672  *         delete this mesh using decrRef() as it is no more needed.  
3673  *  \throw If the coordinates array is not set.
3674  *  \throw If the nodal connectivity of cells is not defined.
3675  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3676  *  \throw If magnitude of \a vec is less than 1e-6.
3677  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3678  *  \throw If \a this includes quadratic cells.
3679  */
3680 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3681 {
3682   checkFullyDefined();
3683   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3684     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3685   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3686   if(candidates->empty())
3687     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3688   std::vector<int> nodes;
3689   DataArrayInt *cellIds1D=0;
3690   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3691   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3692   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3693   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3694   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3695   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3696   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3697   revDesc2=0; revDescIndx2=0;
3698   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3699   revDesc1=0; revDescIndx1=0;
3700   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3701   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3702   //
3703   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3704   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3705     cut3DCurve[*it]=-1;
3706   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3707   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3708   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3709                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3710                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3711   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3712   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3713   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3714   if(cellIds2->empty())
3715     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3716   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3717   ret->setCoords(mDesc1->getCoords());
3718   ret->setConnectivity(conn,connI,true);
3719   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3720   return ret.retn();
3721 }
3722
3723 /*!
3724  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3725 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
3726 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3727 the result mesh.
3728  *  \param [in] origin - 3 components of a point defining location of the plane.
3729  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3730  *         must be greater than 1e-6.
3731  *  \param [in] eps - half-thickness of the plane.
3732  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3733  *         producing correspondent segments. The caller is to delete this array
3734  *         using decrRef() as it is no more needed.
3735  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3736  *         mesh in 3D space. This mesh does not share the node coordinates array with
3737  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3738  *         no more needed. 
3739  *  \throw If the coordinates array is not set.
3740  *  \throw If the nodal connectivity of cells is not defined.
3741  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3742  *  \throw If magnitude of \a vec is less than 1e-6.
3743  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3744  *  \throw If \a this includes quadratic cells.
3745  */
3746 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3747 {
3748   checkFullyDefined();
3749   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3750     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3751   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3752   if(candidates->empty())
3753     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3754   std::vector<int> nodes;
3755   DataArrayInt *cellIds1D=0;
3756   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3757   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3758   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3759   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3761   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3762   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3763   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3764   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3765   //
3766   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3767   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3768     cut3DCurve[*it]=-1;
3769   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3770   int ncellsSub=subMesh->getNumberOfCells();
3771   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3772   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3773                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3774                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3775   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3776   conn->alloc(0,1);
3777   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3778   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3779   for(int i=0;i<ncellsSub;i++)
3780     {
3781       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3782         {
3783           if(cut3DSurf[i].first!=-2)
3784             {
3785               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3786               connI->pushBackSilent(conn->getNumberOfTuples());
3787               cellIds2->pushBackSilent(i);
3788             }
3789           else
3790             {
3791               int cellId3DSurf=cut3DSurf[i].second;
3792               int offset=nodalI[cellId3DSurf]+1;
3793               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3794               for(int j=0;j<nbOfEdges;j++)
3795                 {
3796                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3797                   connI->pushBackSilent(conn->getNumberOfTuples());
3798                   cellIds2->pushBackSilent(cellId3DSurf);
3799                 }
3800             }
3801         }
3802     }
3803   if(cellIds2->empty())
3804     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3805   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3806   ret->setCoords(mDesc1->getCoords());
3807   ret->setConnectivity(conn,connI,true);
3808   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3809   return ret.retn();
3810 }
3811
3812 /*!
3813  * Finds cells whose bounding boxes intersect a given plane.
3814  *  \param [in] origin - 3 components of a point defining location of the plane.
3815  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3816  *         must be greater than 1e-6.
3817  *  \param [in] eps - half-thickness of the plane.
3818  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3819  *         cells. The caller is to delete this array using decrRef() as it is no more
3820  *         needed.
3821  *  \throw If the coordinates array is not set.
3822  *  \throw If the nodal connectivity of cells is not defined.
3823  *  \throw If \a this->getSpaceDimension() != 3.
3824  *  \throw If magnitude of \a vec is less than 1e-6.
3825  *  \sa buildSlice3D()
3826  */
3827 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3828 {
3829   checkFullyDefined();
3830   if(getSpaceDimension()!=3)
3831     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3832   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3833   if(normm<1e-6)
3834     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3835   double vec2[3];
3836   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3837   double angle=acos(vec[2]/normm);
3838   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3839   double bbox[6];
3840   if(angle>eps)
3841     {
3842       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3843       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3844       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3845       mw->setCoords(coo);
3846       mw->getBoundingBox(bbox);
3847       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3848       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3849     }
3850   else
3851     {
3852       getBoundingBox(bbox);
3853       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3854       cellIds=getCellsInBoundingBox(bbox,eps);
3855     }
3856   return cellIds.retn();
3857 }
3858
3859 /*!
3860  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3861  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3862  * No consideration of coordinate is done by this method.
3863  * 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)
3864  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3865  */
3866 bool MEDCouplingUMesh::isContiguous1D() const
3867 {
3868   if(getMeshDimension()!=1)
3869     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3870   int nbCells=getNumberOfCells();
3871   if(nbCells<1)
3872     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3873   const int *connI=_nodal_connec_index->getConstPointer();
3874   const int *conn=_nodal_connec->getConstPointer();
3875   int ref=conn[connI[0]+2];
3876   for(int i=1;i<nbCells;i++)
3877     {
3878       if(conn[connI[i]+1]!=ref)
3879         return false;
3880       ref=conn[connI[i]+2];
3881     }
3882   return true;
3883 }
3884
3885 /*!
3886  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3887  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3888  * \param pt reference point of the line
3889  * \param v normalized director vector of the line
3890  * \param eps max precision before throwing an exception
3891  * \param res output of size this->getNumberOfCells
3892  */
3893 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3894 {
3895   if(getMeshDimension()!=1)
3896     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3897   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3898     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3899   if(getSpaceDimension()!=3)
3900     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3901   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3902   const double *fPtr=f->getArray()->getConstPointer();
3903   double tmp[3];
3904   for(int i=0;i<getNumberOfCells();i++)
3905     {
3906       const double *tmp1=fPtr+3*i;
3907       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3908       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3909       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3910       double n1=INTERP_KERNEL::norm<3>(tmp);
3911       n1/=INTERP_KERNEL::norm<3>(tmp1);
3912       if(n1>eps)
3913         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3914     }
3915   const double *coo=getCoords()->getConstPointer();
3916   for(int i=0;i<getNumberOfNodes();i++)
3917     {
3918       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3919       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3920       res[i]=std::accumulate(tmp,tmp+3,0.);
3921     }
3922 }
3923
3924 /*!
3925  * 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. 
3926  * \a this is expected to be a mesh so that its space dimension is equal to its
3927  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3928  * 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).
3929  *
3930  * 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
3931  * 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).
3932  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3933  *
3934  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3935  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3936  *
3937  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3938  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3939  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3940  * \return the positive value of the distance.
3941  * \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
3942  * dimension - 1.
3943  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3944  */
3945 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3946 {
3947   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3948   if(meshDim!=spaceDim-1)
3949     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3950   if(meshDim!=2 && meshDim!=1)
3951     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3952   checkFullyDefined();
3953   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3954     { 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()); }
3955   DataArrayInt *ret1=0;
3956   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3957   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3958   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3959   cellId=*ret1Safe->begin();
3960   return *ret0->begin();
3961 }
3962
3963 /*!
3964  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3965  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3966  * 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
3967  * 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).
3968  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3969  * 
3970  * \a this is expected to be a mesh so that its space dimension is equal to its
3971  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3972  * 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).
3973  *
3974  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3975  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3976  *
3977  * \param [in] pts the list of points in which each tuple represents a point
3978  * \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.
3979  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3980  * \throw if number of components of \a pts is not equal to the space dimension.
3981  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3982  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3983  */
3984 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3985 {
3986   if(!pts)
3987     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3988   pts->checkAllocated();
3989   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3990   if(meshDim!=spaceDim-1)
3991     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3992   if(meshDim!=2 && meshDim!=1)
3993     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3994   if(pts->getNumberOfComponents()!=spaceDim)
3995     {
3996       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3997       throw INTERP_KERNEL::Exception(oss.str().c_str());
3998     }
3999   checkFullyDefined();
4000   int nbCells=getNumberOfCells();
4001   if(nbCells==0)
4002     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4003   int nbOfPts=pts->getNumberOfTuples();
4004   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4005   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4006   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4007   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4008   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4009   const double *bbox(bboxArr->begin());
4010   switch(spaceDim)
4011   {
4012     case 3:
4013       {
4014         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4015         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4016           {
4017             double x=std::numeric_limits<double>::max();
4018             std::vector<int> elems;
4019             myTree.getMinDistanceOfMax(ptsPtr,x);
4020             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4021             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4022           }
4023         break;
4024       }
4025     case 2:
4026       {
4027         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4028         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4029           {
4030             double x=std::numeric_limits<double>::max();
4031             std::vector<int> elems;
4032             myTree.getMinDistanceOfMax(ptsPtr,x);
4033             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4034             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4035           }
4036         break;
4037       }
4038     default:
4039       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4040   }
4041   cellIds=ret1.retn();
4042   return ret0.retn();
4043 }
4044
4045 /*!
4046  * \param [in] pt the start pointer (included) of the coordinates of the point
4047  * \param [in] cellIdsBg the start pointer (included) of cellIds
4048  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4049  * \param [in] nc nodal connectivity
4050  * \param [in] ncI nodal connectivity index
4051  * \param [in,out] ret0 the min distance between \a this and the external input point
4052  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4053  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4054  */
4055 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)
4056 {
4057   cellId=-1;
4058   ret0=std::numeric_limits<double>::max();
4059   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4060     {
4061       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4062       {
4063         case INTERP_KERNEL::NORM_TRI3:
4064           {
4065             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4066             if(tmp<ret0)
4067               { ret0=tmp; cellId=*zeCell; }
4068             break;
4069           }
4070         case INTERP_KERNEL::NORM_QUAD4:
4071         case INTERP_KERNEL::NORM_POLYGON:
4072           {
4073             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4074             if(tmp<ret0)
4075               { ret0=tmp; cellId=*zeCell; }
4076             break;
4077           }
4078         default:
4079           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4080       }
4081     }
4082 }
4083
4084 /*!
4085  * \param [in] pt the start pointer (included) of the coordinates of the point
4086  * \param [in] cellIdsBg the start pointer (included) of cellIds
4087  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4088  * \param [in] nc nodal connectivity
4089  * \param [in] ncI nodal connectivity index
4090  * \param [in,out] ret0 the min distance between \a this and the external input point
4091  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4092  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4093  */
4094 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)
4095 {
4096   cellId=-1;
4097   ret0=std::numeric_limits<double>::max();
4098   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4099     {
4100       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4101       {
4102         case INTERP_KERNEL::NORM_SEG2:
4103           {
4104             std::size_t uselessEntry=0;
4105             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4106             tmp=sqrt(tmp);
4107             if(tmp<ret0)
4108               { ret0=tmp; cellId=*zeCell; }
4109             break;
4110           }
4111         default:
4112           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4113       }
4114     }
4115 }
4116
4117 /*!
4118  * Finds cells in contact with a ball (i.e. a point with precision). 
4119  * 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.
4120  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4121  *
4122  * \warning This method is suitable if the caller intends to evaluate only one
4123  *          point, for more points getCellsContainingPoints() is recommended as it is
4124  *          faster. 
4125  *  \param [in] pos - array of coordinates of the ball central point.
4126  *  \param [in] eps - ball radius.
4127  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4128  *         if there are no such cells.
4129  *  \throw If the coordinates array is not set.
4130  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4131  */
4132 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4133 {
4134   std::vector<int> elts;
4135   getCellsContainingPoint(pos,eps,elts);
4136   if(elts.empty())
4137     return -1;
4138   return elts.front();
4139 }
4140
4141 /*!
4142  * Finds cells in contact with a ball (i.e. a point with precision).
4143  * 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.
4144  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4145  * \warning This method is suitable if the caller intends to evaluate only one
4146  *          point, for more points getCellsContainingPoints() is recommended as it is
4147  *          faster. 
4148  *  \param [in] pos - array of coordinates of the ball central point.
4149  *  \param [in] eps - ball radius.
4150  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4151  *         before inserting ids.
4152  *  \throw If the coordinates array is not set.
4153  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4154  *
4155  *  \if ENABLE_EXAMPLES
4156  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4157  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4158  *  \endif
4159  */
4160 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4161 {
4162   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4163   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4164   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4165 }
4166
4167 /// @cond INTERNAL
4168
4169 namespace ParaMEDMEM
4170 {
4171   template<const int SPACEDIMM>
4172   class DummyClsMCUG
4173   {
4174   public:
4175     static const int MY_SPACEDIM=SPACEDIMM;
4176     static const int MY_MESHDIM=8;
4177     typedef int MyConnType;
4178     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4179     // begin
4180     // useless, but for windows compilation ...
4181     const double* getCoordinatesPtr() const { return 0; }
4182     const int* getConnectivityPtr() const { return 0; }
4183     const int* getConnectivityIndexPtr() const { return 0; }
4184     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4185     // end
4186   };
4187
4188
4189
4190   /*!
4191    * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4192    */
4193   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map<INTERP_KERNEL::Node *,int>& m)
4194   {
4195     INTERP_KERNEL::Edge *ret=0;
4196     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]));
4197     m[n0]=bg[0]; m[n1]=bg[1];
4198     switch(typ)
4199     {
4200       case INTERP_KERNEL::NORM_SEG2:
4201         {
4202           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4203           break;
4204         }
4205       case INTERP_KERNEL::NORM_SEG3:
4206         {
4207           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4208           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4209           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4210           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4211           bool colinearity(inters.areColinears());
4212           delete e1; delete e2;
4213           if(colinearity)
4214             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4215           else
4216             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4217           break;
4218         }
4219       default:
4220         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4221     }
4222     return ret;
4223   }
4224
4225   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4226   {
4227     INTERP_KERNEL::Edge *ret=0;
4228     switch(typ)
4229     {
4230       case INTERP_KERNEL::NORM_SEG2:
4231         {
4232           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4233           break;
4234         }
4235       case INTERP_KERNEL::NORM_SEG3:
4236         {
4237           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4238           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4239           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4240           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4241           bool colinearity=inters.areColinears();
4242           delete e1; delete e2;
4243           if(colinearity)
4244             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4245           else
4246             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4247           mapp2[bg[2]].second=false;
4248           break;
4249         }
4250       default:
4251         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4252     }
4253     return ret;
4254   }
4255
4256   /*!
4257    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4258    * the global mesh 'mDesc'.
4259    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4260    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4261    */
4262   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4263                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4264   {
4265     mapp.clear();
4266     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.
4267     const double *coo=mDesc->getCoords()->getConstPointer();
4268     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4269     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4270     std::set<int> s;
4271     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4272       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4273     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4274       {
4275         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4276         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4277       }
4278     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4279     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4280       {
4281         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4282         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4283       }
4284     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4285       {
4286         if((*it2).second.second)
4287           mapp[(*it2).second.first]=(*it2).first;
4288         ((*it2).second.first)->decrRef();
4289       }
4290     return ret;
4291   }
4292
4293   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4294   {
4295     if(nodeId>=offset2)
4296       {
4297         int locId=nodeId-offset2;
4298         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4299       }
4300     if(nodeId>=offset1)
4301       {
4302         int locId=nodeId-offset1;
4303         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4304       }
4305     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4306   }
4307
4308   /**
4309    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4310    */
4311   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4312                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4313                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4314   {
4315     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4316       {
4317         int eltId1=abs(*desc1)-1;
4318         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4319           {
4320             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4321             if(it==mappRev.end())
4322               {
4323                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4324                 mapp[node]=*it1;
4325                 mappRev[*it1]=node;
4326               }
4327           }
4328       }
4329   }
4330 }
4331
4332 /// @endcond
4333
4334 template<int SPACEDIM>
4335 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4336                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4337 {
4338   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4339   int *eltsIndexPtr(eltsIndex->getPointer());
4340   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4341   const double *bbox(bboxArr->begin());
4342   int nbOfCells=getNumberOfCells();
4343   const int *conn=_nodal_connec->getConstPointer();
4344   const int *connI=_nodal_connec_index->getConstPointer();
4345   double bb[2*SPACEDIM];
4346   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4347   for(int i=0;i<nbOfPoints;i++)
4348     {
4349       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4350       for(int j=0;j<SPACEDIM;j++)
4351         {
4352           bb[2*j]=pos[SPACEDIM*i+j];
4353           bb[2*j+1]=pos[SPACEDIM*i+j];
4354         }
4355       std::vector<int> candidates;
4356       myTree.getIntersectingElems(bb,candidates);
4357       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4358         {
4359           int sz(connI[(*iter)+1]-connI[*iter]-1);
4360           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4361           bool status(false);
4362           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4363             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4364           else
4365             {
4366               if(SPACEDIM!=2)
4367                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4368               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4369               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4370               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4371               INTERP_KERNEL::QuadraticPolygon *pol(0);
4372               for(int j=0;j<sz;j++)
4373                 {
4374                   int nodeId(conn[connI[*iter]+1+j]);
4375                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4376                 }
4377               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4378                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4379               else
4380                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4381               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4382               double a(0.),b(0.),c(0.);
4383               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4384               status=pol->isInOrOut2(n);
4385               delete pol; n->decrRef();
4386             }
4387           if(status)
4388             {
4389               eltsIndexPtr[i+1]++;
4390               elts->pushBackSilent(*iter);
4391             }
4392         }
4393     }
4394 }
4395 /*!
4396  * Finds cells in contact with several balls (i.e. points with precision).
4397  * This method is an extension of getCellContainingPoint() and
4398  * getCellsContainingPoint() for the case of multiple points.
4399  * 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.
4400  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4401  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4402  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4403  *         this->getSpaceDimension() * \a nbOfPoints 
4404  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4405  *  \param [in] eps - radius of balls (i.e. the precision).
4406  *  \param [out] elts - vector returning ids of found cells.
4407  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4408  *         dividing cell ids in \a elts into groups each referring to one
4409  *         point. Its every element (except the last one) is an index pointing to the
4410  *         first id of a group of cells. For example cells in contact with the *i*-th
4411  *         point are described by following range of indices:
4412  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4413  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4414  *         Number of cells in contact with the *i*-th point is
4415  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4416  *  \throw If the coordinates array is not set.
4417  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4418  *
4419  *  \if ENABLE_EXAMPLES
4420  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4421  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4422  *  \endif
4423  */
4424 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4425                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4426 {
4427   int spaceDim=getSpaceDimension();
4428   int mDim=getMeshDimension();
4429   if(spaceDim==3)
4430     {
4431       if(mDim==3)
4432         {
4433           const double *coords=_coords->getConstPointer();
4434           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4435         }
4436       /*else if(mDim==2)
4437         {
4438
4439         }*/
4440       else
4441         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4442     }
4443   else if(spaceDim==2)
4444     {
4445       if(mDim==2)
4446         {
4447           const double *coords=_coords->getConstPointer();
4448           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4449         }
4450       else
4451         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4452     }
4453   else if(spaceDim==1)
4454     {
4455       if(mDim==1)
4456         {
4457           const double *coords=_coords->getConstPointer();
4458           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4459         }
4460       else
4461         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4462     }
4463   else
4464     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4465 }
4466
4467 /*!
4468  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4469  * least two its edges intersect each other anywhere except their extremities. An
4470  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4471  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4472  *         cleared before filling in.
4473  *  \param [in] eps - precision.
4474  *  \throw If \a this->getMeshDimension() != 2.
4475  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4476  */
4477 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4478 {
4479   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4480   if(getMeshDimension()!=2)
4481     throw INTERP_KERNEL::Exception(msg);
4482   int spaceDim=getSpaceDimension();
4483   if(spaceDim!=2 && spaceDim!=3)
4484     throw INTERP_KERNEL::Exception(msg);
4485   const int *conn=_nodal_connec->getConstPointer();
4486   const int *connI=_nodal_connec_index->getConstPointer();
4487   int nbOfCells=getNumberOfCells();
4488   std::vector<double> cell2DinS2;
4489   for(int i=0;i<nbOfCells;i++)
4490     {
4491       int offset=connI[i];
4492       int nbOfNodesForCell=connI[i+1]-offset-1;
4493       if(nbOfNodesForCell<=3)
4494         continue;
4495       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4496       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4497       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4498         cells.push_back(i);
4499       cell2DinS2.clear();
4500     }
4501 }
4502
4503 /*!
4504  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4505  *
4506  * 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.
4507  * 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.
4508  * 
4509  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4510  * This convex envelop is computed using Jarvis march algorithm.
4511  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4512  * 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)
4513  * 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.
4514  *
4515  * \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.
4516  * \sa MEDCouplingUMesh::colinearize2D
4517  */
4518 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4519 {
4520   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4521     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4522   checkFullyDefined();
4523   const double *coords=getCoords()->getConstPointer();
4524   int nbOfCells=getNumberOfCells();
4525   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4526   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4527   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4528   int *workIndexOut=nodalConnecIndexOut->getPointer();
4529   *workIndexOut=0;
4530   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4531   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4532   std::set<INTERP_KERNEL::NormalizedCellType> types;
4533   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4534   isChanged->alloc(0,1);
4535   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4536     {
4537       int pos=nodalConnecOut->getNumberOfTuples();
4538       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4539         isChanged->pushBackSilent(i);
4540       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4541       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4542     }
4543   if(isChanged->empty())
4544     return 0;
4545   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4546   _types=types;
4547   return isChanged.retn();
4548 }
4549
4550 /*!
4551  * This method is \b NOT const because it can modify \a this.
4552  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4553  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4554  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4555  * \b 1 for translation and rotation around point of 'mesh1D'.
4556  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4557  */
4558 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4559 {
4560   checkFullyDefined();
4561   mesh1D->checkFullyDefined();
4562   if(!mesh1D->isContiguous1D())
4563     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4564   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4565     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4566   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4567     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4568   if(mesh1D->getMeshDimension()!=1)
4569     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4570   bool isQuad=false;
4571   if(isPresenceOfQuadratic())
4572     {
4573       if(mesh1D->isFullyQuadratic())
4574         isQuad=true;
4575       else
4576         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4577     }
4578   zipCoords();
4579   int oldNbOfNodes=getNumberOfNodes();
4580   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4581   switch(policy)
4582   {
4583     case 0:
4584       {
4585         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4586         break;
4587       }
4588     case 1:
4589       {
4590         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4591         break;
4592       }
4593     default:
4594       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4595   }
4596   setCoords(newCoords);
4597   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4598   updateTime();
4599   return ret.retn();
4600 }
4601
4602 /*!
4603  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4604  * If it is not the case an exception will be thrown.
4605  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4606  * intersection of plane defined by ('origin','vec').
4607  * This method has one in/out parameter : 'cut3DCurve'.
4608  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4609  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4610  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4611  * This method will throw an exception if \a this contains a non linear segment.
4612  */
4613 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4614 {
4615   checkFullyDefined();
4616   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4617     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4618   int ncells=getNumberOfCells();
4619   int nnodes=getNumberOfNodes();
4620   double vec2[3],vec3[3],vec4[3];
4621   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4622   if(normm<1e-6)
4623     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4624   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4625   const int *conn=_nodal_connec->getConstPointer();
4626   const int *connI=_nodal_connec_index->getConstPointer();
4627   const double *coo=_coords->getConstPointer();
4628   std::vector<double> addCoo;
4629   for(int i=0;i<ncells;i++)
4630     {
4631       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4632         {
4633           if(cut3DCurve[i]==-2)
4634             {
4635               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4636               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];
4637               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4638               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4639               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4640                 {
4641                   const double *st2=coo+3*st;
4642                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4643                   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]));
4644                   if(pos>eps && pos<1-eps)
4645                     {
4646                       int nNode=((int)addCoo.size())/3;
4647                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4648                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4649                       cut3DCurve[i]=nnodes+nNode;
4650                     }
4651                 }
4652             }
4653         }
4654       else
4655         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4656     }
4657   if(!addCoo.empty())
4658     {
4659       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4660       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4661       coo2->alloc(newNbOfNodes,3);
4662       double *tmp=coo2->getPointer();
4663       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4664       std::copy(addCoo.begin(),addCoo.end(),tmp);
4665       DataArrayDouble::SetArrayIn(coo2,_coords);
4666     }
4667 }
4668
4669 /*!
4670  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4671  * \param mesh1D is the input 1D mesh used for translation computation.
4672  * \return newCoords new coords filled by this method. 
4673  */
4674 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4675 {
4676   int oldNbOfNodes=getNumberOfNodes();
4677   int nbOf1DCells=mesh1D->getNumberOfCells();
4678   int spaceDim=getSpaceDimension();
4679   DataArrayDouble *ret=DataArrayDouble::New();
4680   std::vector<bool> isQuads;
4681   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4682   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4683   double *retPtr=ret->getPointer();
4684   const double *coords=getCoords()->getConstPointer();
4685   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4686   std::vector<int> v;
4687   std::vector<double> c;
4688   double vec[3];
4689   v.reserve(3);
4690   c.reserve(6);
4691   for(int i=0;i<nbOf1DCells;i++)
4692     {
4693       v.resize(0);
4694       mesh1D->getNodeIdsOfCell(i,v);
4695       c.resize(0);
4696       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4697       mesh1D->getCoordinatesOfNode(v[0],c);
4698       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4699       for(int j=0;j<oldNbOfNodes;j++)
4700         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4701       if(isQuad)
4702         {
4703           c.resize(0);
4704           mesh1D->getCoordinatesOfNode(v[1],c);
4705           mesh1D->getCoordinatesOfNode(v[0],c);
4706           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4707           for(int j=0;j<oldNbOfNodes;j++)
4708             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4709         }
4710     }
4711   ret->copyStringInfoFrom(*getCoords());
4712   return ret;
4713 }
4714
4715 /*!
4716  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4717  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4718  * \return newCoords new coords filled by this method. 
4719  */
4720 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4721 {
4722   if(mesh1D->getSpaceDimension()==2)
4723     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4724   if(mesh1D->getSpaceDimension()==3)
4725     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4726   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4727 }
4728
4729 /*!
4730  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4731  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4732  * \return newCoords new coords filled by this method. 
4733  */
4734 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4735 {
4736   if(isQuad)
4737     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4738   int oldNbOfNodes=getNumberOfNodes();
4739   int nbOf1DCells=mesh1D->getNumberOfCells();
4740   if(nbOf1DCells<2)
4741     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4742   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4743   int nbOfLevsInVec=nbOf1DCells+1;
4744   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4745   double *retPtr=ret->getPointer();
4746   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4747   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4748   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4749   tmp->setCoords(tmp2);
4750   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4751   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4752   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4753   for(int i=1;i<nbOfLevsInVec;i++)
4754     {
4755       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4756       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4757       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4758       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4759       tmp->translate(vec);
4760       double tmp3[2],radius,alpha,alpha0;
4761       const double *p0=i+1<nbOfLevsInVec?begin:third;
4762       const double *p1=i+1<nbOfLevsInVec?end:begin;
4763       const double *p2=i+1<nbOfLevsInVec?third:end;
4764       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4765       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]);
4766       double angle=acos(cosangle/(radius*radius));
4767       tmp->rotate(end,0,angle);
4768       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4769     }
4770   return ret.retn();
4771 }
4772
4773 /*!
4774  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4775  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4776  * \return newCoords new coords filled by this method. 
4777  */
4778 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4779 {
4780   if(isQuad)
4781     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4782   int oldNbOfNodes=getNumberOfNodes();
4783   int nbOf1DCells=mesh1D->getNumberOfCells();
4784   if(nbOf1DCells<2)
4785     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4786   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4787   int nbOfLevsInVec=nbOf1DCells+1;
4788   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4789   double *retPtr=ret->getPointer();
4790   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4791   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4792   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4793   tmp->setCoords(tmp2);
4794   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4795   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4796   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4797   for(int i=1;i<nbOfLevsInVec;i++)
4798     {
4799       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4800       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4801       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4802       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4803       tmp->translate(vec);
4804       double tmp3[2],radius,alpha,alpha0;
4805       const double *p0=i+1<nbOfLevsInVec?begin:third;
4806       const double *p1=i+1<nbOfLevsInVec?end:begin;
4807       const double *p2=i+1<nbOfLevsInVec?third:end;
4808       double vecPlane[3]={
4809         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4810         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4811         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4812       };
4813       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4814       if(norm>1.e-7)
4815         {
4816           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4817           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4818           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4819           double s2=norm2;
4820           double c2=cos(asin(s2));
4821           double m[3][3]={
4822             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4823             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4824             {-vec2[1]*s2, vec2[0]*s2, c2}
4825           };
4826           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]};
4827           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]};
4828           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]};
4829           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4830           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]);
4831           double angle=acos(cosangle/(radius*radius));
4832           tmp->rotate(end,vecPlane,angle);
4833         }
4834       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4835     }
4836   return ret.retn();
4837 }
4838
4839 /*!
4840  * This method is private because not easy to use for end user. This method is const contrary to
4841  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4842  * the coords sorted slice by slice.
4843  * \param isQuad specifies presence of quadratic cells.
4844  */
4845 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4846 {
4847   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4848   int nbOf2DCells=getNumberOfCells();
4849   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4850   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4851   const int *conn=_nodal_connec->getConstPointer();
4852   const int *connI=_nodal_connec_index->getConstPointer();
4853   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4854   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4855   newConnI->alloc(nbOf3DCells+1,1);
4856   int *newConnIPtr=newConnI->getPointer();
4857   *newConnIPtr++=0;
4858   std::vector<int> newc;
4859   for(int j=0;j<nbOf2DCells;j++)
4860     {
4861       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4862       *newConnIPtr++=(int)newc.size();
4863     }
4864   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4865   int *newConnPtr=newConn->getPointer();
4866   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4867   newConnIPtr=newConnI->getPointer();
4868   for(int iz=0;iz<nbOf1DCells;iz++)
4869     {
4870       if(iz!=0)
4871         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4872       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4873         {
4874           int icell=(int)(iter-newc.begin());
4875           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4876             {
4877               if(*iter!=-1)
4878                 *newConnPtr=(*iter)+iz*deltaPerLev;
4879               else
4880                 *newConnPtr=-1;
4881             }
4882           else
4883             *newConnPtr=(*iter);
4884         }
4885     }
4886   ret->setConnectivity(newConn,newConnI,true);
4887   ret->setCoords(getCoords());
4888   return ret;
4889 }
4890
4891 /*!
4892  * Checks if \a this mesh is constituted by only quadratic cells.
4893  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4894  *  \throw If the coordinates array is not set.
4895  *  \throw If the nodal connectivity of cells is not defined.
4896  */
4897 bool MEDCouplingUMesh::isFullyQuadratic() const
4898 {
4899   checkFullyDefined();
4900   bool ret=true;
4901   int nbOfCells=getNumberOfCells();
4902   for(int i=0;i<nbOfCells && ret;i++)
4903     {
4904       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4905       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4906       ret=cm.isQuadratic();
4907     }
4908   return ret;
4909 }
4910
4911 /*!
4912  * Checks if \a this mesh includes any quadratic cell.
4913  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4914  *  \throw If the coordinates array is not set.
4915  *  \throw If the nodal connectivity of cells is not defined.
4916  */
4917 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4918 {
4919   checkFullyDefined();
4920   bool ret=false;
4921   int nbOfCells=getNumberOfCells();
4922   for(int i=0;i<nbOfCells && !ret;i++)
4923     {
4924       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4925       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4926       ret=cm.isQuadratic();
4927     }
4928   return ret;
4929 }
4930
4931 /*!
4932  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4933  * this mesh, it remains unchanged.
4934  *  \throw If the coordinates array is not set.
4935  *  \throw If the nodal connectivity of cells is not defined.
4936  */
4937 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4938 {
4939   checkFullyDefined();
4940   int nbOfCells=getNumberOfCells();
4941   int delta=0;
4942   const int *iciptr=_nodal_connec_index->getConstPointer();
4943   for(int i=0;i<nbOfCells;i++)
4944     {
4945       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4946       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4947       if(cm.isQuadratic())
4948         {
4949           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4950           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4951           if(!cml.isDynamic())
4952             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4953           else
4954             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4955         }
4956     }
4957   if(delta==0)
4958     return ;
4959   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4961   const int *icptr=_nodal_connec->getConstPointer();
4962   newConn->alloc(getMeshLength()-delta,1);
4963   newConnI->alloc(nbOfCells+1,1);
4964   int *ocptr=newConn->getPointer();
4965   int *ociptr=newConnI->getPointer();
4966   *ociptr=0;
4967   _types.clear();
4968   for(int i=0;i<nbOfCells;i++,ociptr++)
4969     {
4970       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4971       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4972       if(!cm.isQuadratic())
4973         {
4974           _types.insert(type);
4975           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4976           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4977         }
4978       else
4979         {
4980           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4981           _types.insert(typel);
4982           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4983           int newNbOfNodes=cml.getNumberOfNodes();
4984           if(cml.isDynamic())
4985             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4986           *ocptr++=(int)typel;
4987           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4988           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4989         }
4990     }
4991   setConnectivity(newConn,newConnI,false);
4992 }
4993
4994 /*!
4995  * This method converts all linear cell in \a this to quadratic one.
4996  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4997  * 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)
4998  * 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.
4999  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5000  * end of the existing coordinates.
5001  * 
5002  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5003  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5004  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5005  * 
5006  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5007  *
5008  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5009  */
5010 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5011 {
5012   DataArrayInt *conn=0,*connI=0;
5013   DataArrayDouble *coords=0;
5014   std::set<INTERP_KERNEL::NormalizedCellType> types;
5015   checkFullyDefined();
5016   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5017   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5018   int meshDim=getMeshDimension();
5019   switch(conversionType)
5020   {
5021     case 0:
5022       switch(meshDim)
5023       {
5024         case 1:
5025           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5026           connSafe=conn; connISafe=connI; coordsSafe=coords;
5027           break;
5028         case 2:
5029           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5030           connSafe=conn; connISafe=connI; coordsSafe=coords;
5031           break;
5032         case 3:
5033           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5034           connSafe=conn; connISafe=connI; coordsSafe=coords;
5035           break;
5036         default:
5037           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5038       }
5039       break;
5040         case 1:
5041           {
5042             switch(meshDim)
5043             {
5044               case 1:
5045                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5046                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5047                 break;
5048               case 2:
5049                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5050                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5051                 break;
5052               case 3:
5053                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5054                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5055                 break;
5056               default:
5057                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5058             }
5059             break;
5060           }
5061         default:
5062           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5063   }
5064   setConnectivity(connSafe,connISafe,false);
5065   _types=types;
5066   setCoords(coordsSafe);
5067   return ret.retn();
5068 }
5069
5070 /*!
5071  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5072  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5073  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5074  */
5075 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5076 {
5077   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5078   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5079   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5080   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5081   int nbOfCells=getNumberOfCells();
5082   int nbOfNodes=getNumberOfNodes();
5083   const int *cPtr=_nodal_connec->getConstPointer();
5084   const int *icPtr=_nodal_connec_index->getConstPointer();
5085   int lastVal=0,offset=nbOfNodes;
5086   for(int i=0;i<nbOfCells;i++,icPtr++)
5087     {
5088       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5089       if(type==INTERP_KERNEL::NORM_SEG2)
5090         {
5091           types.insert(INTERP_KERNEL::NORM_SEG3);
5092           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5093           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5094           newConn->pushBackSilent(offset++);
5095           lastVal+=4;
5096           newConnI->pushBackSilent(lastVal);
5097           ret->pushBackSilent(i);
5098         }
5099       else
5100         {
5101           types.insert(type);
5102           lastVal+=(icPtr[1]-icPtr[0]);
5103           newConnI->pushBackSilent(lastVal);
5104           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5105         }
5106     }
5107   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5108   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5109   return ret.retn();
5110 }
5111
5112 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
5113 {
5114   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5115   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5116   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5117   //
5118   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5119   DataArrayInt *conn1D=0,*conn1DI=0;
5120   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5121   DataArrayDouble *coordsTmp=0;
5122   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5123   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5124   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5125   const int *c1DPtr=conn1D->begin();
5126   const int *c1DIPtr=conn1DI->begin();
5127   int nbOfCells=getNumberOfCells();
5128   const int *cPtr=_nodal_connec->getConstPointer();
5129   const int *icPtr=_nodal_connec_index->getConstPointer();
5130   int lastVal=0;
5131   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5132     {
5133       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5134       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5135       if(!cm.isQuadratic())
5136         {
5137           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5138           types.insert(typ2); newConn->pushBackSilent(typ2);
5139           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5140           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5141             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5142           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5143           newConnI->pushBackSilent(lastVal);
5144           ret->pushBackSilent(i);
5145         }
5146       else
5147         {
5148           types.insert(typ);
5149           lastVal+=(icPtr[1]-icPtr[0]);
5150           newConnI->pushBackSilent(lastVal);
5151           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5152         }
5153     }
5154   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5155   return ret.retn();
5156 }
5157
5158 /*!
5159  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5160  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5161  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5162  */
5163 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5164 {
5165   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5166   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5167   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5168 }
5169
5170 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5171 {
5172   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5173   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5174   //
5175   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5176   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5177   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5178   //
5179   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5180   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5181   DataArrayInt *conn1D=0,*conn1DI=0;
5182   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5183   DataArrayDouble *coordsTmp=0;
5184   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5185   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5186   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5187   const int *c1DPtr=conn1D->begin();
5188   const int *c1DIPtr=conn1DI->begin();
5189   int nbOfCells=getNumberOfCells();
5190   const int *cPtr=_nodal_connec->getConstPointer();
5191   const int *icPtr=_nodal_connec_index->getConstPointer();
5192   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5193   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5194     {
5195       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5196       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5197       if(!cm.isQuadratic())
5198         {
5199           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5200           types.insert(typ2); newConn->pushBackSilent(typ2);
5201           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5202           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5203             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5204           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5205           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5206           newConnI->pushBackSilent(lastVal);
5207           ret->pushBackSilent(i);
5208         }
5209       else
5210         {
5211           types.insert(typ);
5212           lastVal+=(icPtr[1]-icPtr[0]);
5213           newConnI->pushBackSilent(lastVal);
5214           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5215         }
5216     }
5217   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5218   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5219   return ret.retn();
5220 }
5221
5222 /*!
5223  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5224  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5225  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5226  */
5227 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5228 {
5229   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5230   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5231   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5232 }
5233
5234 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5235 {
5236   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5237   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5238   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5239   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5240   //
5241   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5242   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5243   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5244   //
5245   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5246   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5247   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5248   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5249   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5250   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5251   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5252   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5253   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5254   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5255   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5256   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5257   int nbOfCells=getNumberOfCells();
5258   const int *cPtr=_nodal_connec->getConstPointer();
5259   const int *icPtr=_nodal_connec_index->getConstPointer();
5260   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5261   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5262     {
5263       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5264       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5265       if(!cm.isQuadratic())
5266         {
5267           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5268           if(typ2==INTERP_KERNEL::NORM_ERROR)
5269             {
5270               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5271               throw INTERP_KERNEL::Exception(oss.str().c_str());
5272             }
5273           types.insert(typ2); newConn->pushBackSilent(typ2);
5274           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5275           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5276             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5277           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5278             {
5279               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5280               int tmpPos=newConn->getNumberOfTuples();
5281               newConn->pushBackSilent(nodeId2);
5282               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5283             }
5284           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5285           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5286           newConnI->pushBackSilent(lastVal);
5287           ret->pushBackSilent(i);
5288         }
5289       else
5290         {
5291           types.insert(typ);
5292           lastVal+=(icPtr[1]-icPtr[0]);
5293           newConnI->pushBackSilent(lastVal);
5294           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5295         }
5296     }
5297   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5298   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5299   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5300   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5301   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5302   int *c=newConn->getPointer();
5303   const int *cI(newConnI->begin());
5304   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5305     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5306   offset=coordsTmp2Safe->getNumberOfTuples();
5307   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5308     c[cI[(*elt)+1]-1]+=offset;
5309   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5310   return ret.retn();
5311 }
5312
5313 /*!
5314  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5315  * so that the number of cells remains the same. Quadratic faces are converted to
5316  * polygons. This method works only for 2D meshes in
5317  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5318  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5319  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5320  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5321  *         a polylinized edge constituting the input polygon.
5322  *  \throw If the coordinates array is not set.
5323  *  \throw If the nodal connectivity of cells is not defined.
5324  *  \throw If \a this->getMeshDimension() != 2.
5325  *  \throw If \a this->getSpaceDimension() != 2.
5326  */
5327 void MEDCouplingUMesh::tessellate2D(double eps)
5328 {
5329   checkFullyDefined();
5330   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5331     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5332   double epsa=fabs(eps);
5333   if(epsa<std::numeric_limits<double>::min())
5334     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 !");
5335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5337   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5339   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5340   revDesc1=0; revDescIndx1=0;
5341   mDesc->tessellate2DCurve(eps);
5342   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5343   setCoords(mDesc->getCoords());
5344 }
5345
5346 /*!
5347  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5348  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5349  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5350  *         a sub-divided edge.
5351  *  \throw If the coordinates array is not set.
5352  *  \throw If the nodal connectivity of cells is not defined.
5353  *  \throw If \a this->getMeshDimension() != 1.
5354  *  \throw If \a this->getSpaceDimension() != 2.
5355  */
5356 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5357 {
5358   checkFullyDefined();
5359   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5360     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5361   double epsa=fabs(eps);
5362   if(epsa<std::numeric_limits<double>::min())
5363     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 !");
5364   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5365   int nbCells=getNumberOfCells();
5366   int nbNodes=getNumberOfNodes();
5367   const int *conn=_nodal_connec->getConstPointer();
5368   const int *connI=_nodal_connec_index->getConstPointer();
5369   const double *coords=_coords->getConstPointer();
5370   std::vector<double> addCoo;
5371   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5372   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5373   newConnI->alloc(nbCells+1,1);
5374   int *newConnIPtr=newConnI->getPointer();
5375   *newConnIPtr=0;
5376   int tmp1[3];
5377   INTERP_KERNEL::Node *tmp2[3];
5378   std::set<INTERP_KERNEL::NormalizedCellType> types;
5379   for(int i=0;i<nbCells;i++,newConnIPtr++)
5380     {
5381       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5382       if(cm.isQuadratic())
5383         {//assert(connI[i+1]-connI[i]-1==3)
5384           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5385           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5386           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5387           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5388           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5389           if(eac)
5390             {
5391               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5392               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5393               delete eac;
5394               newConnIPtr[1]=(int)newConn.size();
5395             }
5396           else
5397             {
5398               types.insert(INTERP_KERNEL::NORM_SEG2);
5399               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5400               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5401               newConnIPtr[1]=newConnIPtr[0]+3;
5402             }
5403         }
5404       else
5405         {
5406           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5407           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5408           newConnIPtr[1]=newConnIPtr[0]+3;
5409         }
5410     }
5411   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5412     return ;
5413   _types=types;
5414   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5415   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5416   newConnArr->alloc((int)newConn.size(),1);
5417   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5418   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5419   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5420   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5421   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5422   std::copy(addCoo.begin(),addCoo.end(),work);
5423   DataArrayDouble::SetArrayIn(newCoords,_coords);
5424   updateTime();
5425 }
5426
5427 /*!
5428  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5429  * In addition, returns an array mapping new cells to old ones. <br>
5430  * This method typically increases the number of cells in \a this mesh
5431  * but the number of nodes remains \b unchanged.
5432  * That's why the 3D splitting policies
5433  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5434  *  \param [in] policy - specifies a pattern used for splitting.
5435  * The semantic of \a policy is:
5436  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5437  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5438  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5439  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5440  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5441  *          an id of old cell producing it. The caller is to delete this array using
5442  *         decrRef() as it is no more needed. 
5443  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5444  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5445  *          and \a this->getMeshDimension() != 3. 
5446  *  \throw If \a policy is not one of the four discussed above.
5447  *  \throw If the nodal connectivity of cells is not defined.
5448  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5449  */
5450 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5451 {
5452   switch(policy)
5453   {
5454     case 0:
5455       return simplexizePol0();
5456     case 1:
5457       return simplexizePol1();
5458     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5459         return simplexizePlanarFace5();
5460     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5461         return simplexizePlanarFace6();
5462     default:
5463       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)");
5464   }
5465 }
5466
5467 /*!
5468  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5469  * - 1D: INTERP_KERNEL::NORM_SEG2
5470  * - 2D: INTERP_KERNEL::NORM_TRI3
5471  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5472  *
5473  * This method is useful for users that need to use P1 field services as
5474  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5475  * All these methods need mesh support containing only simplex cells.
5476  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5477  *  \throw If the coordinates array is not set.
5478  *  \throw If the nodal connectivity of cells is not defined.
5479  *  \throw If \a this->getMeshDimension() < 1.
5480  */
5481 bool MEDCouplingUMesh::areOnlySimplexCells() const
5482 {
5483   checkFullyDefined();
5484   int mdim=getMeshDimension();
5485   if(mdim<1 || mdim>3)
5486     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5487   int nbCells=getNumberOfCells();
5488   const int *conn=_nodal_connec->getConstPointer();
5489   const int *connI=_nodal_connec_index->getConstPointer();
5490   for(int i=0;i<nbCells;i++)
5491     {
5492       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5493       if(!cm.isSimplex())
5494         return false;
5495     }
5496   return true;
5497 }
5498
5499 /*!
5500  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5501  */
5502 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
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]+3],
5527             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],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 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5554  */
5555 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5556 {
5557   checkConnectivityFullyDefined();
5558   if(getMeshDimension()!=2)
5559     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5560   int nbOfCells=getNumberOfCells();
5561   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5562   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5563   ret->alloc(nbOfCells+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+nbOfCutCells+1,1);
5569   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
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_QUAD4)
5578         {
5579           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5580             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5581           pt=std::copy(tmp,tmp+8,pt);
5582           ptI[1]=ptI[0]+4;
5583           ptI[2]=ptI[0]+8;
5584           *retPt++=i;
5585           *retPt++=i;
5586           ptI+=2;
5587         }
5588       else
5589         {
5590           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5591           ptI[1]=ptI[0]+ci[1]-ci[0];
5592           ptI++;
5593           *retPt++=i;
5594         }
5595     }
5596   _nodal_connec->decrRef();
5597   _nodal_connec=newConn.retn();
5598   _nodal_connec_index->decrRef();
5599   _nodal_connec_index=newConnI.retn();
5600   computeTypes();
5601   updateTime();
5602   return ret.retn();
5603 }
5604
5605 /*!
5606  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5607  */
5608 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5609 {
5610   checkConnectivityFullyDefined();
5611   if(getMeshDimension()!=3)
5612     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5613   int nbOfCells=getNumberOfCells();
5614   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5615   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5616   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5617   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5618   int *retPt=ret->getPointer();
5619   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5620   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5621   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5622   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5623   int *pt=newConn->getPointer();
5624   int *ptI=newConnI->getPointer();
5625   ptI[0]=0;
5626   const int *oldc=_nodal_connec->getConstPointer();
5627   const int *ci=_nodal_connec_index->getConstPointer();
5628   for(int i=0;i<nbOfCells;i++,ci++)
5629     {
5630       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5631         {
5632           for(int j=0;j<5;j++,pt+=5,ptI++)
5633             {
5634               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5635               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];
5636               *retPt++=i;
5637               ptI[1]=ptI[0]+5;
5638             }
5639         }
5640       else
5641         {
5642           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5643           ptI[1]=ptI[0]+ci[1]-ci[0];
5644           ptI++;
5645           *retPt++=i;
5646         }
5647     }
5648   _nodal_connec->decrRef();
5649   _nodal_connec=newConn.retn();
5650   _nodal_connec_index->decrRef();
5651   _nodal_connec_index=newConnI.retn();
5652   computeTypes();
5653   updateTime();
5654   return ret.retn();
5655 }
5656
5657 /*!
5658  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5659  */
5660 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5661 {
5662   checkConnectivityFullyDefined();
5663   if(getMeshDimension()!=3)
5664     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5665   int nbOfCells=getNumberOfCells();
5666   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5667   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5668   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5669   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5670   int *retPt=ret->getPointer();
5671   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5672   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5673   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5674   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5675   int *pt=newConn->getPointer();
5676   int *ptI=newConnI->getPointer();
5677   ptI[0]=0;
5678   const int *oldc=_nodal_connec->getConstPointer();
5679   const int *ci=_nodal_connec_index->getConstPointer();
5680   for(int i=0;i<nbOfCells;i++,ci++)
5681     {
5682       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5683         {
5684           for(int j=0;j<6;j++,pt+=5,ptI++)
5685             {
5686               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5687               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];
5688               *retPt++=i;
5689               ptI[1]=ptI[0]+5;
5690             }
5691         }
5692       else
5693         {
5694           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5695           ptI[1]=ptI[0]+ci[1]-ci[0];
5696           ptI++;
5697           *retPt++=i;
5698         }
5699     }
5700   _nodal_connec->decrRef();
5701   _nodal_connec=newConn.retn();
5702   _nodal_connec_index->decrRef();
5703   _nodal_connec_index=newConnI.retn();
5704   computeTypes();
5705   updateTime();
5706   return ret.retn();
5707 }
5708
5709 /*!
5710  * 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.
5711  * This method completly ignore coordinates.
5712  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5713  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5714  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5715  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5716  */
5717 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5718 {
5719   checkFullyDefined();
5720   if(getMeshDimension()!=2)
5721     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5722   int nbOfCells=getNumberOfCells();
5723   int *connI=_nodal_connec_index->getPointer();
5724   int newConnLgth=0;
5725   for(int i=0;i<nbOfCells;i++,connI++)
5726     {
5727       int offset=descIndex[i];
5728       int nbOfEdges=descIndex[i+1]-offset;
5729       //
5730       bool ddirect=desc[offset+nbOfEdges-1]>0;
5731       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5732       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5733       for(int j=0;j<nbOfEdges;j++)
5734         {
5735           bool direct=desc[offset+j]>0;
5736           int edgeId=std::abs(desc[offset+j])-1;
5737           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5738             {
5739               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5740               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5741               int ref2=direct?id1:id2;
5742               if(ref==ref2)
5743                 {
5744                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5745                   newConnLgth+=nbOfSubNodes-1;
5746                   ref=direct?id2:id1;
5747                 }
5748               else
5749                 {
5750                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5751                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5752                 }
5753             }
5754           else
5755             {
5756               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5757             }
5758         }
5759       newConnLgth++;//+1 is for cell type
5760       connI[1]=newConnLgth;
5761     }
5762   //
5763   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5764   newConn->alloc(newConnLgth,1);
5765   int *work=newConn->getPointer();
5766   for(int i=0;i<nbOfCells;i++)
5767     {
5768       *work++=INTERP_KERNEL::NORM_POLYGON;
5769       int offset=descIndex[i];
5770       int nbOfEdges=descIndex[i+1]-offset;
5771       for(int j=0;j<nbOfEdges;j++)
5772         {
5773           bool direct=desc[offset+j]>0;
5774           int edgeId=std::abs(desc[offset+j])-1;
5775           if(direct)
5776             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5777           else
5778             {
5779               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5780               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5781               work=std::copy(it,it+nbOfSubNodes-1,work);
5782             }
5783         }
5784     }
5785   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5786   _types.clear();
5787   if(nbOfCells>0)
5788     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5789 }
5790
5791 /*!
5792  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5793  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5794  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5795  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5796  * so it can be useful to call mergeNodes() before calling this method.
5797  *  \throw If \a this->getMeshDimension() <= 1.
5798  *  \throw If the coordinates array is not set.
5799  *  \throw If the nodal connectivity of cells is not defined.
5800  */
5801 void MEDCouplingUMesh::convertDegeneratedCells()
5802 {
5803   checkFullyDefined();
5804   if(getMeshDimension()<=1)
5805     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5806   int nbOfCells=getNumberOfCells();
5807   if(nbOfCells<1)
5808     return ;
5809   int initMeshLgth=getMeshLength();
5810   int *conn=_nodal_connec->getPointer();
5811   int *index=_nodal_connec_index->getPointer();
5812   int posOfCurCell=0;
5813   int newPos=0;
5814   int lgthOfCurCell;
5815   for(int i=0;i<nbOfCells;i++)
5816     {
5817       lgthOfCurCell=index[i+1]-posOfCurCell;
5818       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5819       int newLgth;
5820       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5821                                                                                                      conn+newPos+1,newLgth);
5822       conn[newPos]=newType;
5823       newPos+=newLgth+1;
5824       posOfCurCell=index[i+1];
5825       index[i+1]=newPos;
5826     }
5827   if(newPos!=initMeshLgth)
5828     _nodal_connec->reAlloc(newPos);
5829   computeTypes();
5830 }
5831
5832 /*!
5833  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5834  * A cell is considered to be oriented correctly if an angle between its
5835  * normal vector and a given vector is less than \c PI / \c 2.
5836  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5837  *         cells. 
5838  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5839  *         checked.
5840  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5841  *         is not cleared before filling in.
5842  *  \throw If \a this->getMeshDimension() != 2.
5843  *  \throw If \a this->getSpaceDimension() != 3.
5844  *
5845  *  \if ENABLE_EXAMPLES
5846  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5847  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5848  *  \endif
5849  */
5850 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5851 {
5852   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5853     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5854   int nbOfCells=getNumberOfCells();
5855   const int *conn=_nodal_connec->getConstPointer();
5856   const int *connI=_nodal_connec_index->getConstPointer();
5857   const double *coordsPtr=_coords->getConstPointer();
5858   for(int i=0;i<nbOfCells;i++)
5859     {
5860       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5861       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5862         {
5863           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5864           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5865             cells.push_back(i);
5866         }
5867     }
5868 }
5869
5870 /*!
5871  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5872  * considered to be oriented correctly if an angle between its normal vector and a
5873  * given vector is less than \c PI / \c 2. 
5874  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5875  *         cells. 
5876  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5877  *         checked.
5878  *  \throw If \a this->getMeshDimension() != 2.
5879  *  \throw If \a this->getSpaceDimension() != 3.
5880  *
5881  *  \if ENABLE_EXAMPLES
5882  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5883  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5884  *  \endif
5885  */
5886 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5887 {
5888   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5889     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5890   int nbOfCells=getNumberOfCells();
5891   int *conn=_nodal_connec->getPointer();
5892   const int *connI=_nodal_connec_index->getConstPointer();
5893   const double *coordsPtr=_coords->getConstPointer();
5894   bool isModified=false;
5895   for(int i=0;i<nbOfCells;i++)
5896     {
5897       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5898       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5899         {
5900           bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5901           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5902             {
5903               isModified=true;
5904               if(!isQuadratic)
5905                 {
5906                   std::vector<int> tmp(connI[i+1]-connI[i]-2);
5907                   std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5908                   std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5909                 }
5910               else
5911                 {
5912                   int sz(((int)(connI[i+1]-connI[i]-1))/2);
5913                   std::vector<int> tmp0(sz-1),tmp1(sz);
5914                   std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5915                   std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5916                   std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5917                   std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5918                 }
5919             }
5920         }
5921     }
5922   if(isModified)
5923     _nodal_connec->declareAsNew();
5924   updateTime();
5925 }
5926
5927 /*!
5928  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5929  * oriented facets. The normal vector of the facet should point out of the cell.
5930  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5931  *         is not cleared before filling in.
5932  *  \throw If \a this->getMeshDimension() != 3.
5933  *  \throw If \a this->getSpaceDimension() != 3.
5934  *  \throw If the coordinates array is not set.
5935  *  \throw If the nodal connectivity of cells is not defined.
5936  *
5937  *  \if ENABLE_EXAMPLES
5938  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5939  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5940  *  \endif
5941  */
5942 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5943 {
5944   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5945     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5946   int nbOfCells=getNumberOfCells();
5947   const int *conn=_nodal_connec->getConstPointer();
5948   const int *connI=_nodal_connec_index->getConstPointer();
5949   const double *coordsPtr=_coords->getConstPointer();
5950   for(int i=0;i<nbOfCells;i++)
5951     {
5952       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5953       if(type==INTERP_KERNEL::NORM_POLYHED)
5954         {
5955           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5956             cells.push_back(i);
5957         }
5958     }
5959 }
5960
5961 /*!
5962  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5963  * out of the cell. 
5964  *  \throw If \a this->getMeshDimension() != 3.
5965  *  \throw If \a this->getSpaceDimension() != 3.
5966  *  \throw If the coordinates array is not set.
5967  *  \throw If the nodal connectivity of cells is not defined.
5968  *  \throw If the reparation fails.
5969  *
5970  *  \if ENABLE_EXAMPLES
5971  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5972  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5973  *  \endif
5974  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5975  */
5976 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5977 {
5978   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5979     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5980   int nbOfCells=getNumberOfCells();
5981   int *conn=_nodal_connec->getPointer();
5982   const int *connI=_nodal_connec_index->getConstPointer();
5983   const double *coordsPtr=_coords->getConstPointer();
5984   for(int i=0;i<nbOfCells;i++)
5985     {
5986       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5987       if(type==INTERP_KERNEL::NORM_POLYHED)
5988         {
5989           try
5990           {
5991               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5992                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5993           }
5994           catch(INTERP_KERNEL::Exception& e)
5995           {
5996               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5997               throw INTERP_KERNEL::Exception(oss.str().c_str());
5998           }
5999         }
6000     }
6001   updateTime();
6002 }
6003
6004 /*!
6005  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6006  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6007  * according to which the first facet of the cell should be oriented to have the normal vector
6008  * pointing out of cell.
6009  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6010  *         cells. The caller is to delete this array using decrRef() as it is no more
6011  *         needed. 
6012  *  \throw If \a this->getMeshDimension() != 3.
6013  *  \throw If \a this->getSpaceDimension() != 3.
6014  *  \throw If the coordinates array is not set.
6015  *  \throw If the nodal connectivity of cells is not defined.
6016  *
6017  *  \if ENABLE_EXAMPLES
6018  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6019  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6020  *  \endif
6021  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6022  */
6023 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6024 {
6025   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6026   if(getMeshDimension()!=3)
6027     throw INTERP_KERNEL::Exception(msg);
6028   int spaceDim=getSpaceDimension();
6029   if(spaceDim!=3)
6030     throw INTERP_KERNEL::Exception(msg);
6031   //
6032   int nbOfCells=getNumberOfCells();
6033   int *conn=_nodal_connec->getPointer();
6034   const int *connI=_nodal_connec_index->getConstPointer();
6035   const double *coo=getCoords()->getConstPointer();
6036   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6037   for(int i=0;i<nbOfCells;i++)
6038     {
6039       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6040       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6041         {
6042           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6043             {
6044               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6045               cells->pushBackSilent(i);
6046             }
6047         }
6048     }
6049   return cells.retn();
6050 }
6051
6052 /*!
6053  * This method is a faster method to correct orientation of all 3D cells in \a this.
6054  * 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.
6055  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6056  * 
6057  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6058  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6059  */
6060 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6061 {
6062   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6063     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6064   int nbOfCells=getNumberOfCells();
6065   int *conn=_nodal_connec->getPointer();
6066   const int *connI=_nodal_connec_index->getConstPointer();
6067   const double *coordsPtr=_coords->getConstPointer();
6068   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6069   for(int i=0;i<nbOfCells;i++)
6070     {
6071       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6072       switch(type)
6073       {
6074         case INTERP_KERNEL::NORM_TETRA4:
6075           {
6076             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6077               {
6078                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6079                 ret->pushBackSilent(i);
6080               }
6081             break;
6082           }
6083         case INTERP_KERNEL::NORM_PYRA5:
6084           {
6085             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6086               {
6087                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6088                 ret->pushBackSilent(i);
6089               }
6090             break;
6091           }
6092         case INTERP_KERNEL::NORM_PENTA6:
6093         case INTERP_KERNEL::NORM_HEXA8:
6094         case INTERP_KERNEL::NORM_HEXGP12:
6095           {
6096             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6097               {
6098                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6099                 ret->pushBackSilent(i);
6100               }
6101             break;
6102           }
6103         case INTERP_KERNEL::NORM_POLYHED:
6104           {
6105             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6106               {
6107                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6108                 ret->pushBackSilent(i);
6109               }
6110             break;
6111           }
6112         default:
6113           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 !");
6114       }
6115     }
6116   updateTime();
6117   return ret.retn();
6118 }
6119
6120 /*!
6121  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6122  * If it is not the case an exception will be thrown.
6123  * This method is fast because the first cell of \a this is used to compute the plane.
6124  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6125  * \param pos output of size at least 3 used to store a point owned of searched plane.
6126  */
6127 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6128 {
6129   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6130     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6131   const int *conn=_nodal_connec->getConstPointer();
6132   const int *connI=_nodal_connec_index->getConstPointer();
6133   const double *coordsPtr=_coords->getConstPointer();
6134   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6135   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6136 }
6137
6138 /*!
6139  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6140  * cells. Currently cells of the following types are treated:
6141  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6142  * For a cell of other type an exception is thrown.
6143  * Space dimension of a 2D mesh can be either 2 or 3.
6144  * The Edge Ratio of a cell \f$t\f$ is: 
6145  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6146  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6147  *  the smallest edge lengths of \f$t\f$.
6148  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6149  *          cells and one time, lying on \a this mesh. The caller is to delete this
6150  *          field using decrRef() as it is no more needed. 
6151  *  \throw If the coordinates array is not set.
6152  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6153  *  \throw If the connectivity data array has more than one component.
6154  *  \throw If the connectivity data array has a named component.
6155  *  \throw If the connectivity index data array has more than one component.
6156  *  \throw If the connectivity index data array has a named component.
6157  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6158  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6159  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6160  */
6161 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6162 {
6163   checkCoherency();
6164   int spaceDim=getSpaceDimension();
6165   int meshDim=getMeshDimension();
6166   if(spaceDim!=2 && spaceDim!=3)
6167     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6168   if(meshDim!=2 && meshDim!=3)
6169     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6170   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6171   ret->setMesh(this);
6172   int nbOfCells=getNumberOfCells();
6173   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6174   arr->alloc(nbOfCells,1);
6175   double *pt=arr->getPointer();
6176   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6177   const int *conn=_nodal_connec->getConstPointer();
6178   const int *connI=_nodal_connec_index->getConstPointer();
6179   const double *coo=_coords->getConstPointer();
6180   double tmp[12];
6181   for(int i=0;i<nbOfCells;i++,pt++)
6182     {
6183       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6184       switch(t)
6185       {
6186         case INTERP_KERNEL::NORM_TRI3:
6187           {
6188             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6189             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6190             break;
6191           }
6192         case INTERP_KERNEL::NORM_QUAD4:
6193           {
6194             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6195             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6196             break;
6197           }
6198         case INTERP_KERNEL::NORM_TETRA4:
6199           {
6200             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6201             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6202             break;
6203           }
6204         default:
6205           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6206       }
6207       conn+=connI[i+1]-connI[i];
6208     }
6209   ret->setName("EdgeRatio");
6210   ret->synchronizeTimeWithSupport();
6211   return ret.retn();
6212 }
6213
6214 /*!
6215  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6216  * cells. Currently cells of the following types are treated:
6217  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6218  * For a cell of other type an exception is thrown.
6219  * Space dimension of a 2D mesh can be either 2 or 3.
6220  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6221  *          cells and one time, lying on \a this mesh. The caller is to delete this
6222  *          field using decrRef() as it is no more needed. 
6223  *  \throw If the coordinates array is not set.
6224  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6225  *  \throw If the connectivity data array has more than one component.
6226  *  \throw If the connectivity data array has a named component.
6227  *  \throw If the connectivity index data array has more than one component.
6228  *  \throw If the connectivity index data array has a named component.
6229  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6230  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6231  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6232  */
6233 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6234 {
6235   checkCoherency();
6236   int spaceDim=getSpaceDimension();
6237   int meshDim=getMeshDimension();
6238   if(spaceDim!=2 && spaceDim!=3)
6239     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6240   if(meshDim!=2 && meshDim!=3)
6241     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6242   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6243   ret->setMesh(this);
6244   int nbOfCells=getNumberOfCells();
6245   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6246   arr->alloc(nbOfCells,1);
6247   double *pt=arr->getPointer();
6248   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6249   const int *conn=_nodal_connec->getConstPointer();
6250   const int *connI=_nodal_connec_index->getConstPointer();
6251   const double *coo=_coords->getConstPointer();
6252   double tmp[12];
6253   for(int i=0;i<nbOfCells;i++,pt++)
6254     {
6255       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6256       switch(t)
6257       {
6258         case INTERP_KERNEL::NORM_TRI3:
6259           {
6260             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6261             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6262             break;
6263           }
6264         case INTERP_KERNEL::NORM_QUAD4:
6265           {
6266             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6267             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6268             break;
6269           }
6270         case INTERP_KERNEL::NORM_TETRA4:
6271           {
6272             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6273             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6274             break;
6275           }
6276         default:
6277           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6278       }
6279       conn+=connI[i+1]-connI[i];
6280     }
6281   ret->setName("AspectRatio");
6282   ret->synchronizeTimeWithSupport();
6283   return ret.retn();
6284 }
6285
6286 /*!
6287  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6288  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6289  * treated: INTERP_KERNEL::NORM_QUAD4.
6290  * For a cell of other type an exception is thrown.
6291  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6292  *          cells and one time, lying on \a this mesh. The caller is to delete this
6293  *          field using decrRef() as it is no more needed. 
6294  *  \throw If the coordinates array is not set.
6295  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6296  *  \throw If the connectivity data array has more than one component.
6297  *  \throw If the connectivity data array has a named component.
6298  *  \throw If the connectivity index data array has more than one component.
6299  *  \throw If the connectivity index data array has a named component.
6300  *  \throw If \a this->getMeshDimension() != 2.
6301  *  \throw If \a this->getSpaceDimension() != 3.
6302  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6303  */
6304 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6305 {
6306   checkCoherency();
6307   int spaceDim=getSpaceDimension();
6308   int meshDim=getMeshDimension();
6309   if(spaceDim!=3)
6310     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6311   if(meshDim!=2)
6312     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6313   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6314   ret->setMesh(this);
6315   int nbOfCells=getNumberOfCells();
6316   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6317   arr->alloc(nbOfCells,1);
6318   double *pt=arr->getPointer();
6319   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6320   const int *conn=_nodal_connec->getConstPointer();
6321   const int *connI=_nodal_connec_index->getConstPointer();
6322   const double *coo=_coords->getConstPointer();
6323   double tmp[12];
6324   for(int i=0;i<nbOfCells;i++,pt++)
6325     {
6326       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6327       switch(t)
6328       {
6329         case INTERP_KERNEL::NORM_QUAD4:
6330           {
6331             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6332             *pt=INTERP_KERNEL::quadWarp(tmp);
6333             break;
6334           }
6335         default:
6336           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6337       }
6338       conn+=connI[i+1]-connI[i];
6339     }
6340   ret->setName("Warp");
6341   ret->synchronizeTimeWithSupport();
6342   return ret.retn();
6343 }
6344
6345
6346 /*!
6347  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6348  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6349  * treated: INTERP_KERNEL::NORM_QUAD4.
6350  * For a cell of other type an exception is thrown.
6351  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6352  *          cells and one time, lying on \a this mesh. The caller is to delete this
6353  *          field using decrRef() as it is no more needed. 
6354  *  \throw If the coordinates array is not set.
6355  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6356  *  \throw If the connectivity data array has more than one component.
6357  *  \throw If the connectivity data array has a named component.
6358  *  \throw If the connectivity index data array has more than one component.
6359  *  \throw If the connectivity index data array has a named component.
6360  *  \throw If \a this->getMeshDimension() != 2.
6361  *  \throw If \a this->getSpaceDimension() != 3.
6362  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6363  */
6364 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6365 {
6366   checkCoherency();
6367   int spaceDim=getSpaceDimension();
6368   int meshDim=getMeshDimension();
6369   if(spaceDim!=3)
6370     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6371   if(meshDim!=2)
6372     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6373   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6374   ret->setMesh(this);
6375   int nbOfCells=getNumberOfCells();
6376   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6377   arr->alloc(nbOfCells,1);
6378   double *pt=arr->getPointer();
6379   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6380   const int *conn=_nodal_connec->getConstPointer();
6381   const int *connI=_nodal_connec_index->getConstPointer();
6382   const double *coo=_coords->getConstPointer();
6383   double tmp[12];
6384   for(int i=0;i<nbOfCells;i++,pt++)
6385     {
6386       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6387       switch(t)
6388       {
6389         case INTERP_KERNEL::NORM_QUAD4:
6390           {
6391             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6392             *pt=INTERP_KERNEL::quadSkew(tmp);
6393             break;
6394           }
6395         default:
6396           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6397       }
6398       conn+=connI[i+1]-connI[i];
6399     }
6400   ret->setName("Skew");
6401   ret->synchronizeTimeWithSupport();
6402   return ret.retn();
6403 }
6404
6405 /*!
6406  * This method aggregate the bbox of each cell and put it into bbox parameter.
6407  * 
6408  * \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)
6409  *                         For all other cases this input parameter is ignored.
6410  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6411  * 
6412  * \throw If \a this is not fully set (coordinates and connectivity).
6413  * \throw If a cell in \a this has no valid nodeId.
6414  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6415  */
6416 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6417 {
6418   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6419   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.
6420     return getBoundingBoxForBBTreeFast();
6421   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6422     {
6423       bool presenceOfQuadratic(false);
6424       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6425         {
6426           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6427           if(cm.isQuadratic())
6428             presenceOfQuadratic=true;
6429         }
6430       if(!presenceOfQuadratic)
6431         return getBoundingBoxForBBTreeFast();
6432       if(mDim==2 && sDim==2)
6433         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6434       else
6435         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6436     }
6437   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) !");
6438 }
6439
6440 /*!
6441  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6442  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6443  * 
6444  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6445  * 
6446  * \throw If \a this is not fully set (coordinates and connectivity).
6447  * \throw If a cell in \a this has no valid nodeId.
6448  */
6449 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6450 {
6451   checkFullyDefined();
6452   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6453   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6454   double *bbox(ret->getPointer());
6455   for(int i=0;i<nbOfCells*spaceDim;i++)
6456     {
6457       bbox[2*i]=std::numeric_limits<double>::max();
6458       bbox[2*i+1]=-std::numeric_limits<double>::max();
6459     }
6460   const double *coordsPtr(_coords->getConstPointer());
6461   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6462   for(int i=0;i<nbOfCells;i++)
6463     {
6464       int offset=connI[i]+1;
6465       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6466       for(int j=0;j<nbOfNodesForCell;j++)
6467         {
6468           int nodeId=conn[offset+j];
6469           if(nodeId>=0 && nodeId<nbOfNodes)
6470             {
6471               for(int k=0;k<spaceDim;k++)
6472                 {
6473                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6474                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6475                 }
6476               kk++;
6477             }
6478         }
6479       if(kk==0)
6480         {
6481           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6482           throw INTERP_KERNEL::Exception(oss.str().c_str());
6483         }
6484     }
6485   return ret.retn();
6486 }
6487
6488 /*!
6489  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6490  * useful for 2D meshes having quadratic cells
6491  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6492  * the two extremities of the arc of circle).
6493  * 
6494  * \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)
6495  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6496  * \throw If \a this is not fully defined.
6497  * \throw If \a this is not a mesh with meshDimension equal to 2.
6498  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6499  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6500  */
6501 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6502 {
6503   checkFullyDefined();
6504   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6505   if(spaceDim!=2 || mDim!=2)
6506     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!");
6507   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6508   double *bbox(ret->getPointer());
6509   const double *coords(_coords->getConstPointer());
6510   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6511   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6512     {
6513       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6514       int sz(connI[1]-connI[0]-1);
6515       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6516       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6517       INTERP_KERNEL::QuadraticPolygon *pol(0);
6518       for(int j=0;j<sz;j++)
6519         {
6520           int nodeId(conn[*connI+1+j]);
6521           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6522         }
6523       if(!cm.isQuadratic())
6524         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6525       else
6526         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6527       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6528       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6529     }
6530   return ret.retn();
6531 }
6532
6533 /*!
6534  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6535  * useful for 2D meshes having quadratic cells
6536  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6537  * the two extremities of the arc of circle).
6538  * 
6539  * \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)
6540  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6541  * \throw If \a this is not fully defined.
6542  * \throw If \a this is not a mesh with meshDimension equal to 1.
6543  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6544  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6545  */
6546 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6547 {
6548   checkFullyDefined();
6549   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6550   if(spaceDim!=2 || mDim!=1)
6551     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!");
6552   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6553   double *bbox(ret->getPointer());
6554   const double *coords(_coords->getConstPointer());
6555   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6556   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6557     {
6558       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6559       int sz(connI[1]-connI[0]-1);
6560       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6561       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6562       INTERP_KERNEL::Edge *edge(0);
6563       for(int j=0;j<sz;j++)
6564         {
6565           int nodeId(conn[*connI+1+j]);
6566           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6567         }
6568       if(!cm.isQuadratic())
6569         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6570       else
6571         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6572       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6573       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6574     }
6575   return ret.retn();
6576 }
6577
6578 /// @cond INTERNAL
6579
6580 namespace ParaMEDMEMImpl
6581 {
6582   class ConnReader
6583   {
6584   public:
6585     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6586     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6587   private:
6588     const int *_conn;
6589     int _val;
6590   };
6591
6592   class ConnReader2
6593   {
6594   public:
6595     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6596     bool operator() (const int& pos) { return _conn[pos]==_val; }
6597   private:
6598     const int *_conn;
6599     int _val;
6600   };
6601 }
6602
6603 /// @endcond
6604
6605 /*!
6606  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6607  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6608  * \a this is composed in cell types.
6609  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6610  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6611  * This parameter is kept only for compatibility with other methode listed above.
6612  */
6613 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6614 {
6615   checkConnectivityFullyDefined();
6616   const int *conn=_nodal_connec->getConstPointer();
6617   const int *connI=_nodal_connec_index->getConstPointer();
6618   const int *work=connI;
6619   int nbOfCells=getNumberOfCells();
6620   std::size_t n=getAllGeoTypes().size();
6621   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6622   std::set<INTERP_KERNEL::NormalizedCellType> types;
6623   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6624     {
6625       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6626       if(types.find(typ)!=types.end())
6627         {
6628           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6629           oss << " is not contiguous !";
6630           throw INTERP_KERNEL::Exception(oss.str().c_str());
6631         }
6632       types.insert(typ);
6633       ret[3*i]=typ;
6634       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6635       ret[3*i+1]=(int)std::distance(work,work2);
6636       work=work2;
6637     }
6638   return ret;
6639 }
6640
6641 /*!
6642  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6643  * only for types cell, type node is not managed.
6644  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6645  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6646  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6647  * If 2 or more same geometric type is in \a code and exception is thrown too.
6648  *
6649  * This method firstly checks
6650  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6651  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6652  * an exception is thrown too.
6653  * 
6654  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6655  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6656  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6657  */
6658 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6659 {
6660   if(code.empty())
6661     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6662   std::size_t sz=code.size();
6663   std::size_t n=sz/3;
6664   if(sz%3!=0)
6665     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6666   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6667   int nb=0;
6668   bool isNoPflUsed=true;
6669   for(std::size_t i=0;i<n;i++)
6670     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6671       {
6672         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6673         nb+=code[3*i+1];
6674         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6675           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6676         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6677       }
6678   if(types.size()!=n)
6679     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6680   if(isNoPflUsed)
6681     {
6682       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6683         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6684       if(types.size()==_types.size())
6685         return 0;
6686     }
6687   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6688   ret->alloc(nb,1);
6689   int *retPtr=ret->getPointer();
6690   const int *connI=_nodal_connec_index->getConstPointer();
6691   const int *conn=_nodal_connec->getConstPointer();
6692   int nbOfCells=getNumberOfCells();
6693   const int *i=connI;
6694   int kk=0;
6695   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6696     {
6697       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6698       int offset=(int)std::distance(connI,i);
6699       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6700       int nbOfCellsOfCurType=(int)std::distance(i,j);
6701       if(code[3*kk+2]==-1)
6702         for(int k=0;k<nbOfCellsOfCurType;k++)
6703           *retPtr++=k+offset;
6704       else
6705         {
6706           int idInIdsPerType=code[3*kk+2];
6707           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6708             {
6709               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6710               if(zePfl)
6711                 {
6712                   zePfl->checkAllocated();
6713                   if(zePfl->getNumberOfComponents()==1)
6714                     {
6715                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6716                         {
6717                           if(*k>=0 && *k<nbOfCellsOfCurType)
6718                             *retPtr=(*k)+offset;
6719                           else
6720                             {
6721                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6722                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6723                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6724                             }
6725                         }
6726                     }
6727                   else
6728                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6729                 }
6730               else
6731                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6732             }
6733           else
6734             {
6735               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6736               oss << " should be in [0," << idsPerType.size() << ") !";
6737               throw INTERP_KERNEL::Exception(oss.str().c_str());
6738             }
6739         }
6740       i=j;
6741     }
6742   return ret.retn();
6743 }
6744
6745 /*!
6746  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6747  * 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.
6748  * 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.
6749  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6750  * 
6751  * \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.
6752  * \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,
6753  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6754  * \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.
6755  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6756  * \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
6757  */
6758 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6759 {
6760   if(!profile)
6761     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6762   if(profile->getNumberOfComponents()!=1)
6763     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6764   checkConnectivityFullyDefined();
6765   const int *conn=_nodal_connec->getConstPointer();
6766   const int *connI=_nodal_connec_index->getConstPointer();
6767   int nbOfCells=getNumberOfCells();
6768   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6769   std::vector<int> typeRangeVals(1);
6770   for(const int *i=connI;i!=connI+nbOfCells;)
6771     {
6772       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6773       if(std::find(types.begin(),types.end(),curType)!=types.end())
6774         {
6775           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6776         }
6777       types.push_back(curType);
6778       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6779       typeRangeVals.push_back((int)std::distance(connI,i));
6780     }
6781   //
6782   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6783   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6784   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6785   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6786   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6787   //
6788   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6789   code.resize(3*nbOfCastsFinal);
6790   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6791   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6792   for(int i=0;i<nbOfCastsFinal;i++)
6793     {
6794       int castId=castsPresent->getIJ(i,0);
6795       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6796       idsInPflPerType2.push_back(tmp3);
6797       code[3*i]=(int)types[castId];
6798       code[3*i+1]=tmp3->getNumberOfTuples();
6799       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6800       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6801         {
6802           tmp4->copyStringInfoFrom(*profile);
6803           idsPerType2.push_back(tmp4);
6804           code[3*i+2]=(int)idsPerType2.size()-1;
6805         }
6806       else
6807         {
6808           code[3*i+2]=-1;
6809         }
6810     }
6811   std::size_t sz2=idsInPflPerType2.size();
6812   idsInPflPerType.resize(sz2);
6813   for(std::size_t i=0;i<sz2;i++)
6814     {
6815       DataArrayInt *locDa=idsInPflPerType2[i];
6816       locDa->incrRef();
6817       idsInPflPerType[i]=locDa;
6818     }
6819   std::size_t sz=idsPerType2.size();
6820   idsPerType.resize(sz);
6821   for(std::size_t i=0;i<sz;i++)
6822     {
6823       DataArrayInt *locDa=idsPerType2[i];
6824       locDa->incrRef();
6825       idsPerType[i]=locDa;
6826     }
6827 }
6828
6829 /*!
6830  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6831  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6832  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6833  * 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.
6834  */
6835 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6836 {
6837   checkFullyDefined();
6838   nM1LevMesh->checkFullyDefined();
6839   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6840     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6841   if(_coords!=nM1LevMesh->getCoords())
6842     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6843   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6844   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6845   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6846   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6847   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6848   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6849   tmp->setConnectivity(tmp0,tmp1);
6850   tmp->renumberCells(ret0->getConstPointer(),false);
6851   revDesc=tmp->getNodalConnectivity();
6852   revDescIndx=tmp->getNodalConnectivityIndex();
6853   DataArrayInt *ret=0;
6854   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6855     {
6856       int tmp2;
6857       ret->getMaxValue(tmp2);
6858       ret->decrRef();
6859       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6860       throw INTERP_KERNEL::Exception(oss.str().c_str());
6861     }
6862   nM1LevMeshIds=ret;
6863   //
6864   revDesc->incrRef();
6865   revDescIndx->incrRef();
6866   ret1->incrRef();
6867   ret0->incrRef();
6868   meshnM1Old2New=ret0;
6869   return ret1;
6870 }
6871
6872 /*!
6873  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6874  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6875  * in "Old to New" mode.
6876  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6877  *          this array using decrRef() as it is no more needed.
6878  *  \throw If the nodal connectivity of cells is not defined.
6879  */
6880 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6881 {
6882   checkConnectivityFullyDefined();
6883   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6884   renumberCells(ret->getConstPointer(),false);
6885   return ret.retn();
6886 }
6887
6888 /*!
6889  * This methods checks that cells are sorted by their types.
6890  * This method makes asumption (no check) that connectivity is correctly set before calling.
6891  */
6892 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6893 {
6894   checkFullyDefined();
6895   const int *conn=_nodal_connec->getConstPointer();
6896   const int *connI=_nodal_connec_index->getConstPointer();
6897   int nbOfCells=getNumberOfCells();
6898   std::set<INTERP_KERNEL::NormalizedCellType> types;
6899   for(const int *i=connI;i!=connI+nbOfCells;)
6900     {
6901       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6902       if(types.find(curType)!=types.end())
6903         return false;
6904       types.insert(curType);
6905       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6906     }
6907   return true;
6908 }
6909
6910 /*!
6911  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6912  * The geometric type order is specified by MED file.
6913  * 
6914  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6915  */
6916 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6917 {
6918   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6919 }
6920
6921 /*!
6922  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6923  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6924  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6925  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6926  */
6927 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6928 {
6929   checkFullyDefined();
6930   const int *conn=_nodal_connec->getConstPointer();
6931   const int *connI=_nodal_connec_index->getConstPointer();
6932   int nbOfCells=getNumberOfCells();
6933   if(nbOfCells==0)
6934     return true;
6935   int lastPos=-1;
6936   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6937   for(const int *i=connI;i!=connI+nbOfCells;)
6938     {
6939       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6940       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6941       if(isTypeExists!=orderEnd)
6942         {
6943           int pos=(int)std::distance(orderBg,isTypeExists);
6944           if(pos<=lastPos)
6945             return false;
6946           lastPos=pos;
6947           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6948         }
6949       else
6950         {
6951           if(sg.find(curType)==sg.end())
6952             {
6953               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6954               sg.insert(curType);
6955             }
6956           else
6957             return false;
6958         }
6959     }
6960   return true;
6961 }
6962
6963 /*!
6964  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6965  * 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
6966  * 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'.
6967  */
6968 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6969 {
6970   checkConnectivityFullyDefined();
6971   int nbOfCells=getNumberOfCells();
6972   const int *conn=_nodal_connec->getConstPointer();
6973   const int *connI=_nodal_connec_index->getConstPointer();
6974   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6975   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6976   tmpa->alloc(nbOfCells,1);
6977   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6978   tmpb->fillWithZero();
6979   int *tmp=tmpa->getPointer();
6980   int *tmp2=tmpb->getPointer();
6981   for(const int *i=connI;i!=connI+nbOfCells;i++)
6982     {
6983       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6984       if(where!=orderEnd)
6985         {
6986           int pos=(int)std::distance(orderBg,where);
6987           tmp2[pos]++;
6988           tmp[std::distance(connI,i)]=pos;
6989         }
6990       else
6991         {
6992           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6993           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6994           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6995           throw INTERP_KERNEL::Exception(oss.str().c_str());
6996         }
6997     }
6998   nbPerType=tmpb.retn();
6999   return tmpa.retn();
7000 }
7001
7002 /*!
7003  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7004  *
7005  * \return a new object containing the old to new correspondance.
7006  *
7007  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7008  */
7009 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7010 {
7011   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7012 }
7013
7014 /*!
7015  * 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.
7016  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7017  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7018  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7019  */
7020 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7021 {
7022   DataArrayInt *nbPerType=0;
7023   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7024   nbPerType->decrRef();
7025   return tmpa->buildPermArrPerLevel();
7026 }
7027
7028 /*!
7029  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7030  * The number of cells remains unchanged after the call of this method.
7031  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7032  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7033  *
7034  * \return the array giving the correspondance old to new.
7035  */
7036 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7037 {
7038   checkFullyDefined();
7039   computeTypes();
7040   const int *conn=_nodal_connec->getConstPointer();
7041   const int *connI=_nodal_connec_index->getConstPointer();
7042   int nbOfCells=getNumberOfCells();
7043   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7044   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7045     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7046       {
7047         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7048         types.push_back(curType);
7049         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7050       }
7051   DataArrayInt *ret=DataArrayInt::New();
7052   ret->alloc(nbOfCells,1);
7053   int *retPtr=ret->getPointer();
7054   std::fill(retPtr,retPtr+nbOfCells,-1);
7055   int newCellId=0;
7056   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7057     {
7058       for(const int *i=connI;i!=connI+nbOfCells;i++)
7059         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7060           retPtr[std::distance(connI,i)]=newCellId++;
7061     }
7062   renumberCells(retPtr,false);
7063   return ret;
7064 }
7065
7066 /*!
7067  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7068  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7069  * This method makes asumption that connectivity is correctly set before calling.
7070  */
7071 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7072 {
7073   checkConnectivityFullyDefined();
7074   const int *conn=_nodal_connec->getConstPointer();
7075   const int *connI=_nodal_connec_index->getConstPointer();
7076   int nbOfCells=getNumberOfCells();
7077   std::vector<MEDCouplingUMesh *> ret;
7078   for(const int *i=connI;i!=connI+nbOfCells;)
7079     {
7080       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7081       int beginCellId=(int)std::distance(connI,i);
7082       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7083       int endCellId=(int)std::distance(connI,i);
7084       int sz=endCellId-beginCellId;
7085       int *cells=new int[sz];
7086       for(int j=0;j<sz;j++)
7087         cells[j]=beginCellId+j;
7088       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7089       delete [] cells;
7090       ret.push_back(m);
7091     }
7092   return ret;
7093 }
7094
7095 /*!
7096  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7097  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7098  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7099  *
7100  * \return a newly allocated instance, that the caller must manage.
7101  * \throw If \a this contains more than one geometric type.
7102  * \throw If the nodal connectivity of \a this is not fully defined.
7103  * \throw If the internal data is not coherent.
7104  */
7105 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7106 {
7107   checkConnectivityFullyDefined();
7108   if(_types.size()!=1)
7109     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7110   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7111   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7112   ret->setCoords(getCoords());
7113   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7114   if(retC)
7115     {
7116       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7117       retC->setNodalConnectivity(c);
7118     }
7119   else
7120     {
7121       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7122       if(!retD)
7123         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7124       DataArrayInt *c=0,*ci=0;
7125       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7126       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7127       retD->setNodalConnectivity(cs,cis);
7128     }
7129   return ret.retn();
7130 }
7131
7132 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7133 {
7134   checkConnectivityFullyDefined();
7135   if(_types.size()!=1)
7136     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7137   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7138   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7139   if(cm.isDynamic())
7140     {
7141       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7142       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7143       throw INTERP_KERNEL::Exception(oss.str().c_str());
7144     }
7145   int nbCells=getNumberOfCells();
7146   int typi=(int)typ;
7147   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7148   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7149   int *outPtr=connOut->getPointer();
7150   const int *conn=_nodal_connec->begin();
7151   const int *connI=_nodal_connec_index->begin();
7152   nbNodesPerCell++;
7153   for(int i=0;i<nbCells;i++,connI++)
7154     {
7155       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7156         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7157       else
7158         {
7159           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 << ") !";
7160           throw INTERP_KERNEL::Exception(oss.str().c_str());
7161         }
7162     }
7163   return connOut.retn();
7164 }
7165
7166 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7167 {
7168   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7169   checkConnectivityFullyDefined();
7170   if(_types.size()!=1)
7171     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7172   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7173   if(lgth<nbCells)
7174     throw INTERP_KERNEL::Exception(msg0);
7175   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7176   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7177   int *cp(c->getPointer()),*cip(ci->getPointer());
7178   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7179   cip[0]=0;
7180   for(int i=0;i<nbCells;i++,cip++,incip++)
7181     {
7182       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7183       int delta(stop-strt);
7184       if(delta>=1)
7185         {
7186           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7187             cp=std::copy(incp+strt,incp+stop,cp);
7188           else
7189             throw INTERP_KERNEL::Exception(msg0);
7190         }
7191       else
7192         throw INTERP_KERNEL::Exception(msg0);
7193       cip[1]=cip[0]+delta;
7194     }
7195   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7196 }
7197
7198 /*!
7199  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7200  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7201  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7202  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7203  * are not used here to avoid the build of big permutation array.
7204  *
7205  * \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
7206  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7207  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7208  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7209  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7210  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7211  * \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
7212  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7213  */
7214 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7215                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7216                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7217 {
7218   std::vector<const MEDCouplingUMesh *> ms2;
7219   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7220     if(*it)
7221       {
7222         (*it)->checkConnectivityFullyDefined();
7223         ms2.push_back(*it);
7224       }
7225   if(ms2.empty())
7226     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7227   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7228   int meshDim=ms2[0]->getMeshDimension();
7229   std::vector<const MEDCouplingUMesh *> m1ssm;
7230   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7231   //
7232   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7233   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7234   int fake=0,rk=0;
7235   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7236   ret1->alloc(0,1); ret2->alloc(0,1);
7237   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7238     {
7239       if(meshDim!=(*it)->getMeshDimension())
7240         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7241       if(refCoo!=(*it)->getCoords())
7242         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7243       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7244       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7245       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7246       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7247         {
7248           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7249           m1ssmSingleAuto.push_back(singleCell);
7250           m1ssmSingle.push_back(singleCell);
7251           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7252         }
7253     }
7254   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7255   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7256   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7257   for(std::size_t i=0;i<m1ssm.size();i++)
7258     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7259   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7260   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7261   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7262   return ret0.retn();
7263 }
7264
7265 /*!
7266  * This method returns a newly created DataArrayInt instance.
7267  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7268  */
7269 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7270 {
7271   checkFullyDefined();
7272   const int *conn=_nodal_connec->getConstPointer();
7273   const int *connIndex=_nodal_connec_index->getConstPointer();
7274   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7275   for(const int *w=begin;w!=end;w++)
7276     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7277       ret->pushBackSilent(*w);
7278   return ret.retn();
7279 }
7280
7281 /*!
7282  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7283  * are in [0:getNumberOfCells())
7284  */
7285 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7286 {
7287   checkFullyDefined();
7288   const int *conn=_nodal_connec->getConstPointer();
7289   const int *connI=_nodal_connec_index->getConstPointer();
7290   int nbOfCells=getNumberOfCells();
7291   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7292   int *tmp=new int[nbOfCells];
7293   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7294     {
7295       int j=0;
7296       for(const int *i=connI;i!=connI+nbOfCells;i++)
7297         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7298           tmp[std::distance(connI,i)]=j++;
7299     }
7300   DataArrayInt *ret=DataArrayInt::New();
7301   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7302   ret->copyStringInfoFrom(*da);
7303   int *retPtr=ret->getPointer();
7304   const int *daPtr=da->getConstPointer();
7305   int nbOfElems=da->getNbOfElems();
7306   for(int k=0;k<nbOfElems;k++)
7307     retPtr[k]=tmp[daPtr[k]];
7308   delete [] tmp;
7309   return ret;
7310 }
7311
7312 /*!
7313  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7314  * This method \b works \b for mesh sorted by type.
7315  * cells whose ids is in 'idsPerGeoType' array.
7316  * This method conserves coords and name of mesh.
7317  */
7318 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7319 {
7320   std::vector<int> code=getDistributionOfTypes();
7321   std::size_t nOfTypesInThis=code.size()/3;
7322   int sz=0,szOfType=0;
7323   for(std::size_t i=0;i<nOfTypesInThis;i++)
7324     {
7325       if(code[3*i]!=type)
7326         sz+=code[3*i+1];
7327       else
7328         szOfType=code[3*i+1];
7329     }
7330   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7331     if(*work<0 || *work>=szOfType)
7332       {
7333         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7334         oss << ". It should be in [0," << szOfType << ") !";
7335         throw INTERP_KERNEL::Exception(oss.str().c_str());
7336       }
7337   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7338   int *idsPtr=idsTokeep->getPointer();
7339   int offset=0;
7340   for(std::size_t i=0;i<nOfTypesInThis;i++)
7341     {
7342       if(code[3*i]!=type)
7343         for(int j=0;j<code[3*i+1];j++)
7344           *idsPtr++=offset+j;
7345       else
7346         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7347       offset+=code[3*i+1];
7348     }
7349   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7350   ret->copyTinyInfoFrom(this);
7351   return ret.retn();
7352 }
7353
7354 /*!
7355  * This method returns a vector of size 'this->getNumberOfCells()'.
7356  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7357  */
7358 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7359 {
7360   int ncell=getNumberOfCells();
7361   std::vector<bool> ret(ncell);
7362   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7363   const int *c=getNodalConnectivity()->getConstPointer();
7364   for(int i=0;i<ncell;i++)
7365     {
7366       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7367       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7368       ret[i]=cm.isQuadratic();
7369     }
7370   return ret;
7371 }
7372
7373 /*!
7374  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7375  */
7376 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7377 {
7378   if(other->getType()!=UNSTRUCTURED)
7379     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7380   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7381   return MergeUMeshes(this,otherC);
7382 }
7383
7384 /*!
7385  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7386  * computed by averaging coordinates of cell nodes, so this method is not a right
7387  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7388  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7389  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7390  *          components. The caller is to delete this array using decrRef() as it is
7391  *          no more needed.
7392  *  \throw If the coordinates array is not set.
7393  *  \throw If the nodal connectivity of cells is not defined.
7394  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7395  */
7396 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7397 {
7398   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7399   int spaceDim=getSpaceDimension();
7400   int nbOfCells=getNumberOfCells();
7401   ret->alloc(nbOfCells,spaceDim);
7402   ret->copyStringInfoFrom(*getCoords());
7403   double *ptToFill=ret->getPointer();
7404   const int *nodal=_nodal_connec->getConstPointer();
7405   const int *nodalI=_nodal_connec_index->getConstPointer();
7406   const double *coor=_coords->getConstPointer();
7407   for(int i=0;i<nbOfCells;i++)
7408     {
7409       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7410       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7411       ptToFill+=spaceDim;
7412     }
7413   return ret.retn();
7414 }
7415
7416 /*!
7417  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7418  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7419  * 
7420  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7421  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7422  * 
7423  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7424  * \throw If \a this is not fully defined (coordinates and connectivity)
7425  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7426  */
7427 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7428 {
7429   checkFullyDefined();
7430   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7431   int spaceDim=getSpaceDimension();
7432   int nbOfCells=getNumberOfCells();
7433   int nbOfNodes=getNumberOfNodes();
7434   ret->alloc(nbOfCells,spaceDim);
7435   double *ptToFill=ret->getPointer();
7436   const int *nodal=_nodal_connec->getConstPointer();
7437   const int *nodalI=_nodal_connec_index->getConstPointer();
7438   const double *coor=_coords->getConstPointer();
7439   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7440     {
7441       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7442       std::fill(ptToFill,ptToFill+spaceDim,0.);
7443       if(type!=INTERP_KERNEL::NORM_POLYHED)
7444         {
7445           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7446             {
7447               if(*conn>=0 && *conn<nbOfNodes)
7448                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7449               else
7450                 {
7451                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7452                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7453                 }
7454             }
7455           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7456           if(nbOfNodesInCell>0)
7457             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7458           else
7459             {
7460               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7461               throw INTERP_KERNEL::Exception(oss.str().c_str());
7462             }
7463         }
7464       else
7465         {
7466           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7467           s.erase(-1);
7468           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7469             {
7470               if(*it>=0 && *it<nbOfNodes)
7471                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7472               else
7473                 {
7474                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7475                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7476                 }
7477             }
7478           if(!s.empty())
7479             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7480           else
7481             {
7482               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7483               throw INTERP_KERNEL::Exception(oss.str().c_str());
7484             }
7485         }
7486     }
7487   return ret.retn();
7488 }
7489
7490 /*!
7491  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7492  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7493  * are specified via an array of cell ids. 
7494  *  \warning Validity of the specified cell ids is not checked! 
7495  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7496  *  \param [in] begin - an array of cell ids of interest.
7497  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7498  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7499  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7500  *          caller is to delete this array using decrRef() as it is no more needed. 
7501  *  \throw If the coordinates array is not set.
7502  *  \throw If the nodal connectivity of cells is not defined.
7503  *
7504  *  \if ENABLE_EXAMPLES
7505  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7506  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7507  *  \endif
7508  */
7509 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7510 {
7511   DataArrayDouble *ret=DataArrayDouble::New();
7512   int spaceDim=getSpaceDimension();
7513   int nbOfTuple=(int)std::distance(begin,end);
7514   ret->alloc(nbOfTuple,spaceDim);
7515   double *ptToFill=ret->getPointer();
7516   double *tmp=new double[spaceDim];
7517   const int *nodal=_nodal_connec->getConstPointer();
7518   const int *nodalI=_nodal_connec_index->getConstPointer();
7519   const double *coor=_coords->getConstPointer();
7520   for(const int *w=begin;w!=end;w++)
7521     {
7522       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7523       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7524       ptToFill+=spaceDim;
7525     }
7526   delete [] tmp;
7527   return ret;
7528 }
7529
7530 /*!
7531  * 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".
7532  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7533  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7534  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7535  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7536  * 
7537  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7538  * \throw If spaceDim!=3 or meshDim!=2.
7539  * \throw If connectivity of \a this is invalid.
7540  * \throw If connectivity of a cell in \a this points to an invalid node.
7541  */
7542 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7543 {
7544   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7545   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7546   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7547     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7548   ret->alloc(nbOfCells,4);
7549   double *retPtr(ret->getPointer());
7550   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7551   const double *coor(_coords->begin());
7552   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7553     {
7554       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7555       if(nodalI[1]-nodalI[0]>=3)
7556         {
7557           for(int j=0;j<3;j++)
7558             {
7559               int nodeId(nodal[nodalI[0]+1+j]);
7560               if(nodeId>=0 && nodeId<nbOfNodes)
7561                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7562               else
7563                 {
7564                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7565                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7566                 }
7567             }
7568         }
7569       else
7570         {
7571           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7572           throw INTERP_KERNEL::Exception(oss.str().c_str());
7573         }
7574       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7575       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7576     }
7577   return ret.retn();
7578 }
7579
7580 /*!
7581  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7582  * 
7583  */
7584 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7585 {
7586   if(!da)
7587     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7588   da->checkAllocated();
7589   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7590   ret->setCoords(da);
7591   int nbOfTuples=da->getNumberOfTuples();
7592   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7593   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7594   c->alloc(2*nbOfTuples,1);
7595   cI->alloc(nbOfTuples+1,1);
7596   int *cp=c->getPointer();
7597   int *cip=cI->getPointer();
7598   *cip++=0;
7599   for(int i=0;i<nbOfTuples;i++)
7600     {
7601       *cp++=INTERP_KERNEL::NORM_POINT1;
7602       *cp++=i;
7603       *cip++=2*(i+1);
7604     }
7605   ret->setConnectivity(c,cI,true);
7606   return ret.retn();
7607 }
7608 /*!
7609  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7610  * Cells and nodes of
7611  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7612  *  \param [in] mesh1 - the first mesh.
7613  *  \param [in] mesh2 - the second mesh.
7614  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7615  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7616  *          is no more needed.
7617  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7618  *  \throw If the coordinates array is not set in none of the meshes.
7619  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7620  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7621  */
7622 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7623 {
7624   std::vector<const MEDCouplingUMesh *> tmp(2);
7625   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7626   return MergeUMeshes(tmp);
7627 }
7628
7629 /*!
7630  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7631  * Cells and nodes of
7632  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7633  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7634  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7635  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7636  *          is no more needed.
7637  *  \throw If \a a.size() == 0.
7638  *  \throw If \a a[ *i* ] == NULL.
7639  *  \throw If the coordinates array is not set in none of the meshes.
7640  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7641  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7642  */
7643 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7644 {
7645   std::size_t sz=a.size();
7646   if(sz==0)
7647     return MergeUMeshesLL(a);
7648   for(std::size_t ii=0;ii<sz;ii++)
7649     if(!a[ii])
7650       {
7651         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7652         throw INTERP_KERNEL::Exception(oss.str().c_str());
7653       }
7654   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7655   std::vector< const MEDCouplingUMesh * > aa(sz);
7656   int spaceDim=-3;
7657   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7658     {
7659       const MEDCouplingUMesh *cur=a[i];
7660       const DataArrayDouble *coo=cur->getCoords();
7661       if(coo)
7662         spaceDim=coo->getNumberOfComponents();
7663     }
7664   if(spaceDim==-3)
7665     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7666   for(std::size_t i=0;i<sz;i++)
7667     {
7668       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7669       aa[i]=bb[i];
7670     }
7671   return MergeUMeshesLL(aa);
7672 }
7673
7674 /// @cond INTERNAL
7675
7676 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7677 {
7678   if(a.empty())
7679     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7680   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7681   int meshDim=(*it)->getMeshDimension();
7682   int nbOfCells=(*it)->getNumberOfCells();
7683   int meshLgth=(*it++)->getMeshLength();
7684   for(;it!=a.end();it++)
7685     {
7686       if(meshDim!=(*it)->getMeshDimension())
7687         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7688       nbOfCells+=(*it)->getNumberOfCells();
7689       meshLgth+=(*it)->getMeshLength();
7690     }
7691   std::vector<const MEDCouplingPointSet *> aps(a.size());
7692   std::copy(a.begin(),a.end(),aps.begin());
7693   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7694   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7695   ret->setCoords(pts);
7696   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7697   c->alloc(meshLgth,1);
7698   int *cPtr=c->getPointer();
7699   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7700   cI->alloc(nbOfCells+1,1);
7701   int *cIPtr=cI->getPointer();
7702   *cIPtr++=0;
7703   int offset=0;
7704   int offset2=0;
7705   for(it=a.begin();it!=a.end();it++)
7706     {
7707       int curNbOfCell=(*it)->getNumberOfCells();
7708       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7709       const int *curC=(*it)->_nodal_connec->getConstPointer();
7710       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7711       for(int j=0;j<curNbOfCell;j++)
7712         {
7713           const int *src=curC+curCI[j];
7714           *cPtr++=*src++;
7715           for(;src!=curC+curCI[j+1];src++,cPtr++)
7716             {
7717               if(*src!=-1)
7718                 *cPtr=*src+offset2;
7719               else
7720                 *cPtr=-1;
7721             }
7722         }
7723       offset+=curCI[curNbOfCell];
7724       offset2+=(*it)->getNumberOfNodes();
7725     }
7726   //
7727   ret->setConnectivity(c,cI,true);
7728   return ret.retn();
7729 }
7730
7731 /// @endcond
7732
7733 /*!
7734  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7735  * dimension and sharing the node coordinates array.
7736  * All cells of the first mesh precede all cells of the second mesh
7737  * within the result mesh. 
7738  *  \param [in] mesh1 - the first mesh.
7739  *  \param [in] mesh2 - the second mesh.
7740  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7741  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7742  *          is no more needed.
7743  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7744  *  \throw If the meshes do not share the node coordinates array.
7745  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7746  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7747  */
7748 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7749 {
7750   std::vector<const MEDCouplingUMesh *> tmp(2);
7751   tmp[0]=mesh1; tmp[1]=mesh2;
7752   return MergeUMeshesOnSameCoords(tmp);
7753 }
7754
7755 /*!
7756  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7757  * dimension and sharing the node coordinates array.
7758  * All cells of the *i*-th mesh precede all cells of the
7759  * (*i*+1)-th mesh within the result mesh.
7760  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7761  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7762  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7763  *          is no more needed.
7764  *  \throw If \a a.size() == 0.
7765  *  \throw If \a a[ *i* ] == NULL.
7766  *  \throw If the meshes do not share the node coordinates array.
7767  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7768  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7769  */
7770 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7771 {
7772   if(meshes.empty())
7773     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7774   for(std::size_t ii=0;ii<meshes.size();ii++)
7775     if(!meshes[ii])
7776       {
7777         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7778         throw INTERP_KERNEL::Exception(oss.str().c_str());
7779       }
7780   const DataArrayDouble *coords=meshes.front()->getCoords();
7781   int meshDim=meshes.front()->getMeshDimension();
7782   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7783   int meshLgth=0;
7784   int meshIndexLgth=0;
7785   for(;iter!=meshes.end();iter++)
7786     {
7787       if(coords!=(*iter)->getCoords())
7788         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7789       if(meshDim!=(*iter)->getMeshDimension())
7790         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7791       meshLgth+=(*iter)->getMeshLength();
7792       meshIndexLgth+=(*iter)->getNumberOfCells();
7793     }
7794   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7795   nodal->alloc(meshLgth,1);
7796   int *nodalPtr=nodal->getPointer();
7797   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7798   nodalIndex->alloc(meshIndexLgth+1,1);
7799   int *nodalIndexPtr=nodalIndex->getPointer();
7800   int offset=0;
7801   for(iter=meshes.begin();iter!=meshes.end();iter++)
7802     {
7803       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7804       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7805       int nbOfCells=(*iter)->getNumberOfCells();
7806       int meshLgth2=(*iter)->getMeshLength();
7807       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7808       if(iter!=meshes.begin())
7809         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7810       else
7811         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7812       offset+=meshLgth2;
7813     }
7814   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7815   ret->setName("merge");
7816   ret->setMeshDimension(meshDim);
7817   ret->setConnectivity(nodal,nodalIndex,true);
7818   ret->setCoords(coords);
7819   return ret;
7820 }
7821
7822 /*!
7823  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7824  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7825  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7826  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7827  * New" mode are returned for each input mesh.
7828  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7829  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7830  *          valid values [0,1,2], see zipConnectivityTraducer().
7831  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7832  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7833  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7834  *          no more needed.
7835  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7836  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7837  *          is no more needed.
7838  *  \throw If \a meshes.size() == 0.
7839  *  \throw If \a meshes[ *i* ] == NULL.
7840  *  \throw If the meshes do not share the node coordinates array.
7841  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7842  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7843  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7844  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7845  */
7846 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7847 {
7848   //All checks are delegated to MergeUMeshesOnSameCoords
7849   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7850   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7851   corr.resize(meshes.size());
7852   std::size_t nbOfMeshes=meshes.size();
7853   int offset=0;
7854   const int *o2nPtr=o2n->getConstPointer();
7855   for(std::size_t i=0;i<nbOfMeshes;i++)
7856     {
7857       DataArrayInt *tmp=DataArrayInt::New();
7858       int curNbOfCells=meshes[i]->getNumberOfCells();
7859       tmp->alloc(curNbOfCells,1);
7860       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7861       offset+=curNbOfCells;
7862       tmp->setName(meshes[i]->getName());
7863       corr[i]=tmp;
7864     }
7865   return ret.retn();
7866 }
7867
7868 /*!
7869  * Makes all given meshes share the nodal connectivity array. The common connectivity
7870  * array is created by concatenating the connectivity arrays of all given meshes. All
7871  * the given meshes must be of the same space dimension but dimension of cells **can
7872  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7873  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7874  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7875  *  \param [in,out] meshes - a vector of meshes to update.
7876  *  \throw If any of \a meshes is NULL.
7877  *  \throw If the coordinates array is not set in any of \a meshes.
7878  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7879  *  \throw If \a meshes are of different space dimension.
7880  */
7881 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7882 {
7883   std::size_t sz=meshes.size();
7884   if(sz==0 || sz==1)
7885     return;
7886   std::vector< const DataArrayDouble * > coords(meshes.size());
7887   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7888   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7889     {
7890       if((*it))
7891         {
7892           (*it)->checkConnectivityFullyDefined();
7893           const DataArrayDouble *coo=(*it)->getCoords();
7894           if(coo)
7895             *it2=coo;
7896           else
7897             {
7898               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7899               oss << " has no coordinate array defined !";
7900               throw INTERP_KERNEL::Exception(oss.str().c_str());
7901             }
7902         }
7903       else
7904         {
7905           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7906           oss << " is null !";
7907           throw INTERP_KERNEL::Exception(oss.str().c_str());
7908         }
7909     }
7910   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7911   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7912   int offset=(*it)->getNumberOfNodes();
7913   (*it++)->setCoords(res);
7914   for(;it!=meshes.end();it++)
7915     {
7916       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7917       (*it)->setCoords(res);
7918       (*it)->shiftNodeNumbersInConn(offset);
7919       offset+=oldNumberOfNodes;
7920     }
7921 }
7922
7923 /*!
7924  * Merges nodes coincident with a given precision within all given meshes that share
7925  * the nodal connectivity array. The given meshes **can be of different** mesh
7926  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7927  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7928  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7929  *  \param [in,out] meshes - a vector of meshes to update.
7930  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7931  *  \throw If any of \a meshes is NULL.
7932  *  \throw If the \a meshes do not share the same node coordinates array.
7933  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7934  */
7935 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7936 {
7937   if(meshes.empty())
7938     return ;
7939   std::set<const DataArrayDouble *> s;
7940   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7941     {
7942       if(*it)
7943         s.insert((*it)->getCoords());
7944       else
7945         {
7946           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 !";
7947           throw INTERP_KERNEL::Exception(oss.str().c_str());
7948         }
7949     }
7950   if(s.size()!=1)
7951     {
7952       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 !";
7953       throw INTERP_KERNEL::Exception(oss.str().c_str());
7954     }
7955   const DataArrayDouble *coo=*(s.begin());
7956   if(!coo)
7957     return;
7958   //
7959   DataArrayInt *comm,*commI;
7960   coo->findCommonTuples(eps,-1,comm,commI);
7961   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7962   int oldNbOfNodes=coo->getNumberOfTuples();
7963   int newNbOfNodes;
7964   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7965   if(oldNbOfNodes==newNbOfNodes)
7966     return ;
7967   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7968   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7969     {
7970       (*it)->renumberNodesInConn(o2n->getConstPointer());
7971       (*it)->setCoords(newCoords);
7972     } 
7973 }
7974
7975 /*!
7976  * 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.
7977  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7978  * \param isQuad specifies the policy of connectivity.
7979  * @ret in/out parameter in which the result will be append
7980  */
7981 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7982 {
7983   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7984   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7985   ret.push_back(cm.getExtrudedType());
7986   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7987   switch(flatType)
7988   {
7989     case INTERP_KERNEL::NORM_POINT1:
7990       {
7991         ret.push_back(connBg[1]);
7992         ret.push_back(connBg[1]+nbOfNodesPerLev);
7993         break;
7994       }
7995     case INTERP_KERNEL::NORM_SEG2:
7996       {
7997         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7998         ret.insert(ret.end(),conn,conn+4);
7999         break;
8000       }
8001     case INTERP_KERNEL::NORM_SEG3:
8002       {
8003         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8004         ret.insert(ret.end(),conn,conn+8);
8005         break;
8006       }
8007     case INTERP_KERNEL::NORM_QUAD4:
8008       {
8009         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8010         ret.insert(ret.end(),conn,conn+8);
8011         break;
8012       }
8013     case INTERP_KERNEL::NORM_TRI3:
8014       {
8015         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8016         ret.insert(ret.end(),conn,conn+6);
8017         break;
8018       }
8019     case INTERP_KERNEL::NORM_TRI6:
8020       {
8021         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,
8022           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8023         ret.insert(ret.end(),conn,conn+15);
8024         break;
8025       }
8026     case INTERP_KERNEL::NORM_QUAD8:
8027       {
8028         int conn[20]={
8029           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8030           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8031           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8032         };
8033         ret.insert(ret.end(),conn,conn+20);
8034         break;
8035       }
8036     case INTERP_KERNEL::NORM_POLYGON:
8037       {
8038         std::back_insert_iterator< std::vector<int> > ii(ret);
8039         std::copy(connBg+1,connEnd,ii);
8040         *ii++=-1;
8041         std::reverse_iterator<const int *> rConnBg(connEnd);
8042         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8043         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8044         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8045         for(std::size_t i=0;i<nbOfRadFaces;i++)
8046           {
8047             *ii++=-1;
8048             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8049             std::copy(conn,conn+4,ii);
8050           }
8051         break;
8052       }
8053     default:
8054       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8055   }
8056 }
8057
8058 /*!
8059  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8060  */
8061 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8062 {
8063   std::size_t i, ip1;
8064   double v[3]={0.,0.,0.};
8065   std::size_t sz=std::distance(begin,end);
8066   if(isQuadratic)
8067     sz/=2;
8068   for(i=0;i<sz;i++)
8069     {
8070       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];
8071       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8072       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8073     }
8074   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8075
8076   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8077   // SEG3 forming a circle):
8078   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8079     {
8080       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8081       for(std::size_t j=0;j<sz;j++)
8082         {
8083           if (j%2)  // current point i is quadratic, next point i+1 is standard
8084             {
8085               i = sz+j;
8086               ip1 = (j+1)%sz; // ip1 = "i+1"
8087             }
8088           else      // current point i is standard, next point i+1 is quadratic
8089             {
8090               i = j;
8091               ip1 = j+sz;
8092             }
8093           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8094           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8095           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8096         }
8097       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8098     }
8099   return (ret>0.);
8100 }
8101
8102 /*!
8103  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8104  */
8105 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8106 {
8107   std::vector<std::pair<int,int> > edges;
8108   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8109   const int *bgFace=begin;
8110   for(std::size_t i=0;i<nbOfFaces;i++)
8111     {
8112       const int *endFace=std::find(bgFace+1,end,-1);
8113       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8114       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8115         {
8116           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8117           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8118             return false;
8119           edges.push_back(p1);
8120         }
8121       bgFace=endFace+1;
8122     }
8123   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8124 }
8125
8126 /*!
8127  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8128  */
8129 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8130 {
8131   double vec0[3],vec1[3];
8132   std::size_t sz=std::distance(begin,end);
8133   if(sz%2!=0)
8134     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8135   int nbOfNodes=(int)sz/2;
8136   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8137   const double *pt0=coords+3*begin[0];
8138   const double *pt1=coords+3*begin[nbOfNodes];
8139   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8140   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8141 }
8142
8143 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8144 {
8145   std::size_t sz=std::distance(begin,end);
8146   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8147   std::size_t nbOfNodes(sz/2);
8148   std::copy(begin,end,(int *)tmp);
8149   for(std::size_t j=1;j<nbOfNodes;j++)
8150     {
8151       begin[j]=tmp[nbOfNodes-j];
8152       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8153     }
8154 }
8155
8156 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8157 {
8158   std::size_t sz=std::distance(begin,end);
8159   if(sz!=4)
8160     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8161   double vec0[3],vec1[3];
8162   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8163   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]; 
8164   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;
8165 }
8166
8167 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8168 {
8169   std::size_t sz=std::distance(begin,end);
8170   if(sz!=5)
8171     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8172   double vec0[3];
8173   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8174   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8175   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8176 }
8177
8178 /*!
8179  * 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 ) 
8180  * 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
8181  * a 2D space.
8182  *
8183  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8184  * \param [in] coords the coordinates with nb of components exactly equal to 3
8185  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8186  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8187  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8188  */
8189 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8190 {
8191   int nbFaces=std::count(begin+1,end,-1)+1;
8192   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8193   double *vPtr=v->getPointer();
8194   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8195   double *pPtr=p->getPointer();
8196   const int *stFaceConn=begin+1;
8197   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8198     {
8199       const int *endFaceConn=std::find(stFaceConn,end,-1);
8200       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8201       stFaceConn=endFaceConn+1;
8202     }
8203   pPtr=p->getPointer(); vPtr=v->getPointer();
8204   DataArrayInt *comm1=0,*commI1=0;
8205   v->findCommonTuples(eps,-1,comm1,commI1);
8206   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8207   const int *comm1Ptr=comm1->getConstPointer();
8208   const int *commI1Ptr=commI1->getConstPointer();
8209   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8210   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8211   //
8212   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8213   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8214   mm->finishInsertingCells();
8215   //
8216   for(int i=0;i<nbOfGrps1;i++)
8217     {
8218       int vecId=comm1Ptr[commI1Ptr[i]];
8219       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8220       DataArrayInt *comm2=0,*commI2=0;
8221       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8222       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8223       const int *comm2Ptr=comm2->getConstPointer();
8224       const int *commI2Ptr=commI2->getConstPointer();
8225       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8226       for(int j=0;j<nbOfGrps2;j++)
8227         {
8228           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8229             {
8230               res->insertAtTheEnd(begin,end);
8231               res->pushBackSilent(-1);
8232             }
8233           else
8234             {
8235               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8236               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8237               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8238               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8239               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8240               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8241               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8242               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8243               const int *idsNodePtr=idsNode->getConstPointer();
8244               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];
8245               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8246               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8247               if(std::abs(norm)>eps)
8248                 {
8249                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8250                   mm3->rotate(center,vec,angle);
8251                 }
8252               mm3->changeSpaceDimension(2);
8253               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8254               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8255               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8256               int nbOfCells=mm4->getNumberOfCells();
8257               for(int k=0;k<nbOfCells;k++)
8258                 {
8259                   int l=0;
8260                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8261                     res->pushBackSilent(idsNodePtr[*work]);
8262                   res->pushBackSilent(-1);
8263                 }
8264             }
8265         }
8266     }
8267   res->popBackSilent();
8268 }
8269
8270 /*!
8271  * 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
8272  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8273  * 
8274  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8275  * \param [in] coords coordinates expected to have 3 components.
8276  * \param [in] begin start of the nodal connectivity of the face.
8277  * \param [in] end end of the nodal connectivity (excluded) of the face.
8278  * \param [out] v the normalized vector of size 3
8279  * \param [out] p the pos of plane
8280  */
8281 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8282 {
8283   std::size_t nbPoints=std::distance(begin,end);
8284   if(nbPoints<3)
8285     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8286   double vec[3]={0.,0.,0.};
8287   std::size_t j=0;
8288   bool refFound=false;
8289   for(;j<nbPoints-1 && !refFound;j++)
8290     {
8291       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8292       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8293       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8294       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8295       if(norm>eps)
8296         {
8297           refFound=true;
8298           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8299         }
8300     }
8301   for(std::size_t i=j;i<nbPoints-1;i++)
8302     {
8303       double curVec[3];
8304       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8305       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8306       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8307       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8308       if(norm<eps)
8309         continue;
8310       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8311       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];
8312       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8313       if(norm>eps)
8314         {
8315           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8316           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8317           return ;
8318         }
8319     }
8320   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8321 }
8322
8323 /*!
8324  * This method tries to obtain a well oriented polyhedron.
8325  * If the algorithm fails, an exception will be thrown.
8326  */
8327 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8328 {
8329   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8330   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8331   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8332   isPerm[0]=true;
8333   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8334   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8335   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8336   //
8337   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8338     {
8339       bgFace=begin;
8340       std::size_t smthChanged=0;
8341       for(std::size_t i=0;i<nbOfFaces;i++)
8342         {
8343           endFace=std::find(bgFace+1,end,-1);
8344           nbOfEdgesInFace=std::distance(bgFace,endFace);
8345           if(!isPerm[i])
8346             {
8347               bool b;
8348               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8349                 {
8350                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8351                   std::pair<int,int> p2(p1.second,p1.first);
8352                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8353                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8354                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8355                 }
8356               if(isPerm[i])
8357                 { 
8358                   if(!b)
8359                     std::reverse(bgFace+1,endFace);
8360                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8361                     {
8362                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8363                       std::pair<int,int> p2(p1.second,p1.first);
8364                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8365                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8366                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8367                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8368                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8369                       if(it!=edgesOK.end())
8370                         {
8371                           edgesOK.erase(it);
8372                           edgesFinished.push_back(p1);
8373                         }
8374                       else
8375                         edgesOK.push_back(p1);
8376                     }
8377                 }
8378             }
8379           bgFace=endFace+1;
8380         }
8381       if(smthChanged==0)
8382         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8383     }
8384   if(!edgesOK.empty())
8385     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8386   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8387     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8388       bgFace=begin;
8389       for(std::size_t i=0;i<nbOfFaces;i++)
8390         {
8391           endFace=std::find(bgFace+1,end,-1);
8392           std::reverse(bgFace+1,endFace);
8393           bgFace=endFace+1;
8394         }
8395     }
8396 }
8397
8398 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8399 {
8400   int nbOfNodesExpected(skin->getNumberOfNodes());
8401   const int *n2oPtr(n2o->getConstPointer());
8402   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8403   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8404   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8405   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8406   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8407   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8408   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8409   if(nbOfNodesExpected<1)
8410     return ret.retn();
8411   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8412   *work++=n2oPtr[prevNode];
8413   for(int i=1;i<nbOfNodesExpected;i++)
8414     {
8415       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8416         {
8417           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8418           conn.erase(prevNode);
8419           if(conn.size()==1)
8420             {
8421               int curNode(*(conn.begin()));
8422               *work++=n2oPtr[curNode];
8423               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8424               shar.erase(prevCell);
8425               if(shar.size()==1)
8426                 {
8427                   prevCell=*(shar.begin());
8428                   prevNode=curNode;
8429                 }
8430               else
8431                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8432             }
8433           else
8434             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8435         }
8436       else
8437         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8438     }
8439   return ret.retn();
8440 }
8441
8442 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8443 {
8444   int nbOfNodesExpected(skin->getNumberOfNodes());
8445   int nbOfTurn(nbOfNodesExpected/2);
8446   const int *n2oPtr(n2o->getConstPointer());
8447   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8448   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8449   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8450   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8451   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8452   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8453   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8454   if(nbOfNodesExpected<1)
8455     return ret.retn();
8456   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8457   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8458   for(int i=1;i<nbOfTurn;i++)
8459     {
8460       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8461         {
8462           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8463           conn.erase(prevNode);
8464           if(conn.size()==1)
8465             {
8466               int curNode(*(conn.begin()));
8467               *work=n2oPtr[curNode];
8468               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8469               shar.erase(prevCell);
8470               if(shar.size()==1)
8471                 {
8472                   int curCell(*(shar.begin()));
8473                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8474                   prevCell=curCell;
8475                   prevNode=curNode;
8476                   work++;
8477                 }
8478               else
8479                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8480             }
8481           else
8482             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8483         }
8484       else
8485         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8486     }
8487   return ret.retn();
8488 }
8489
8490 /*!
8491  * This method makes the assumption spacedimension == meshdimension == 2.
8492  * This method works only for linear cells.
8493  * 
8494  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8495  */
8496 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8497 {
8498   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8499     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8500   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8501   int oldNbOfNodes(skin->getNumberOfNodes());
8502   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8503   int nbOfNodesExpected(skin->getNumberOfNodes());
8504   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8505   int nbCells(skin->getNumberOfCells());
8506   if(nbCells==nbOfNodesExpected)
8507     return buildUnionOf2DMeshLinear(skin,n2o);
8508   else if(2*nbCells==nbOfNodesExpected)
8509     return buildUnionOf2DMeshQuadratic(skin,n2o);
8510   else
8511     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8512 }
8513
8514 /*!
8515  * This method makes the assumption spacedimension == meshdimension == 3.
8516  * This method works only for linear cells.
8517  * 
8518  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8519  */
8520 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8521 {
8522   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8523     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8524   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8525   const int *conn=m->getNodalConnectivity()->getConstPointer();
8526   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8527   int nbOfCells=m->getNumberOfCells();
8528   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8529   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8530   if(nbOfCells<1)
8531     return ret.retn();
8532   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8533   for(int i=1;i<nbOfCells;i++)
8534     {
8535       *work++=-1;
8536       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8537     }
8538   return ret.retn();
8539 }
8540
8541 /*!
8542  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8543  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8544  */
8545 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8546 {
8547   double *w=zipFrmt;
8548   if(spaceDim==3)
8549     for(int i=0;i<nbOfNodesInCell;i++)
8550       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8551   else if(spaceDim==2)
8552     {
8553       for(int i=0;i<nbOfNodesInCell;i++)
8554         {
8555           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8556           *w++=0.;
8557         }
8558     }
8559   else
8560     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8561 }
8562
8563 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8564 {
8565   int nbOfCells=getNumberOfCells();
8566   if(nbOfCells<=0)
8567     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8568   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};
8569   ofs << "  <" << getVTKDataSetType() << ">\n";
8570   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8571   ofs << "      <PointData>\n" << pointData << std::endl;
8572   ofs << "      </PointData>\n";
8573   ofs << "      <CellData>\n" << cellData << std::endl;
8574   ofs << "      </CellData>\n";
8575   ofs << "      <Points>\n";
8576   if(getSpaceDimension()==3)
8577     _coords->writeVTK(ofs,8,"Points",byteData);
8578   else
8579     {
8580       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8581       coo->writeVTK(ofs,8,"Points",byteData);
8582     }
8583   ofs << "      </Points>\n";
8584   ofs << "      <Cells>\n";
8585   const int *cPtr=_nodal_connec->getConstPointer();
8586   const int *cIPtr=_nodal_connec_index->getConstPointer();
8587   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8588   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8589   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8590   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8591   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8592   int szFaceOffsets=0,szConn=0;
8593   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8594     {
8595       *w2=cPtr[cIPtr[i]];
8596       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8597         {
8598           *w1=-1;
8599           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8600           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8601         }
8602       else
8603         {
8604           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8605           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8606           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8607           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8608           w4=std::copy(c.begin(),c.end(),w4);
8609         }
8610     }
8611   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8612   types->writeVTK(ofs,8,"UInt8","types",byteData);
8613   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8614   if(szFaceOffsets!=0)
8615     {//presence of Polyhedra
8616       connectivity->reAlloc(szConn);
8617       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8618       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8619       w1=faces->getPointer();
8620       for(int i=0;i<nbOfCells;i++)
8621         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8622           {
8623             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8624             *w1++=nbFaces;
8625             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8626             for(int j=0;j<nbFaces;j++)
8627               {
8628                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8629                 *w1++=(int)std::distance(w6,w5);
8630                 w1=std::copy(w6,w5,w1);
8631                 w6=w5+1;
8632               }
8633           }
8634       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8635     }
8636   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8637   ofs << "      </Cells>\n";
8638   ofs << "    </Piece>\n";
8639   ofs << "  </" << getVTKDataSetType() << ">\n";
8640 }
8641
8642 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8643 {
8644   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8645   if(_mesh_dim==-2)
8646     { stream << " Not set !"; return ; }
8647   stream << " Mesh dimension : " << _mesh_dim << ".";
8648   if(_mesh_dim==-1)
8649     return ;
8650   if(!_coords)
8651     { stream << " No coordinates set !"; return ; }
8652   if(!_coords->isAllocated())
8653     { stream << " Coordinates set but not allocated !"; return ; }
8654   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8655   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8656   if(!_nodal_connec_index)
8657     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8658   if(!_nodal_connec_index->isAllocated())
8659     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8660   int lgth=_nodal_connec_index->getNumberOfTuples();
8661   int cpt=_nodal_connec_index->getNumberOfComponents();
8662   if(cpt!=1 || lgth<1)
8663     return ;
8664   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8665 }
8666
8667 std::string MEDCouplingUMesh::getVTKDataSetType() const
8668 {
8669   return std::string("UnstructuredGrid");
8670 }
8671
8672 std::string MEDCouplingUMesh::getVTKFileExtension() const
8673 {
8674   return std::string("vtu");
8675 }
8676
8677 /*!
8678  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8679  * returns a result mesh constituted by polygons.
8680  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8681  * all nodes from m2.
8682  * The meshes should be in 2D space. In
8683  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8684  * meshes.
8685  *  \param [in] m1 - the first input mesh which is a partitioned object.
8686  *  \param [in] m2 - the second input mesh which is a partition tool.
8687  *  \param [in] eps - precision used to detect coincident mesh entities.
8688  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8689  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8690  *         this array using decrRef() as it is no more needed.
8691  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8692  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8693  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8694  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8695  *         it is no more needed.  
8696  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8697  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8698  *         is no more needed.  
8699  *  \throw If the coordinates array is not set in any of the meshes.
8700  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8701  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8702  */
8703 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8704                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8705 {
8706   if(!m1 || !m2)
8707     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8708   m1->checkFullyDefined();
8709   m2->checkFullyDefined();
8710   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8711     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8712
8713   // Step 1: compute all edge intersections (new nodes)
8714   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8715   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8716   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8717   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8718   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8719                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8720                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8721   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8722   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8723   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8724
8725   // Step 2: re-order newly created nodes according to the ordering found in m2
8726   std::vector< std::vector<int> > intersectEdge2;
8727   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8728   subDiv2.clear(); dd5=0; dd6=0;
8729
8730   // Step 3:
8731   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8732   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8733   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8734                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8735
8736   // Step 4: Prepare final result:
8737   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8738   addCooDa->alloc((int)(addCoo.size())/2,2);
8739   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8740   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8741   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8742   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8743   std::vector<const DataArrayDouble *> coordss(4);
8744   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8745   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8746   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8747   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8748   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8749   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8750   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8751   ret->setConnectivity(conn,connI,true);
8752   ret->setCoords(coo);
8753   cellNb1=c1.retn(); cellNb2=c2.retn();
8754   return ret.retn();
8755 }
8756
8757 //tony to put in private of MEDCouplingUMesh
8758 MEDCouplingUMesh *BuildMesh1DCutFrom(const MEDCouplingUMesh *mesh1D, const std::vector< std::vector<int> >& intersectEdge2, const DataArrayDouble *coords1, const std::vector<double>& addCoo)
8759 {
8760   int nCells(mesh1D->getNumberOfCells());
8761   if(nCells!=(int)intersectEdge2.size())
8762     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
8763   const DataArrayDouble *coo2(mesh1D->getCoords());
8764   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
8765   const double *coo2Ptr(coo2->begin());
8766   int offset1(coords1->getNumberOfTuples());
8767   int offset2(offset1+coo2->getNumberOfTuples());
8768   int offset3(offset2+addCoo.size()/2);
8769   std::vector<double> addCooQuad;
8770   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
8771   int tmp[4],cicnt(0);
8772   for(int i=0;i<nCells;i++)
8773     {
8774       std::map<INTERP_KERNEL::Node *,int> m;
8775       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
8776       const std::vector<int>& subEdges(intersectEdge2[i]);
8777       int nbSubEdge(subEdges.size()/2);
8778       for(int j=0;j<nbSubEdge;j++)
8779         {
8780           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n1(MEDCouplingUMeshBuildQPNode(subEdges[2*j],coords1->begin(),offset1,coo2Ptr,offset2,addCoo));
8781           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n2(MEDCouplingUMeshBuildQPNode(subEdges[2*j+1],coords1->begin(),offset1,coo2Ptr,offset2,addCoo));
8782           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
8783           INTERP_KERNEL::Edge *e2Ptr(e2);
8784           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
8785             {
8786               tmp[0]=INTERP_KERNEL::NORM_SEG3;
8787               tmp[1]=subEdges[2*j]; tmp[2]=subEdges[2*j+1];
8788               cicnt+=4;
8789               cOut->insertAtTheEnd(tmp,tmp+4);
8790               ciOut->pushBackSilent(cicnt);
8791             }
8792           else
8793             {
8794               tmp[0]=INTERP_KERNEL::NORM_SEG2;
8795               tmp[1]=subEdges[2*j]; tmp[2]=subEdges[2*j+1]; tmp[3]=offset3+(int)addCooQuad.size()/2;
8796               cicnt+=3;
8797               cOut->insertAtTheEnd(tmp,tmp+3);
8798               ciOut->pushBackSilent(cicnt);
8799             }
8800         }
8801       //INTERP_KERNEL::Edge *e2(e->buildEdgeLyingOnMe());
8802       for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
8803         (*it2).first->decrRef();
8804       e->decrRef();
8805     }
8806   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
8807   ret->setConnectivity(cOut,ciOut,true);
8808   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
8809   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8810   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
8811   std::vector<const DataArrayDouble *> coordss(4);
8812   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
8813   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
8814   ret->setCoords(arr);
8815   return ret.retn();
8816 }
8817
8818 /*!
8819  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
8820  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8821  * all nodes from \a mesh1D.
8822  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
8823  *
8824  * \param [in] mesh2D - the 2D mesh (spacedim=meshdim=2) to be intersected using \a mesh1D tool.
8825  * \param [in] mesh1D - the 1D mesh (spacedim=2 meshdim=1) the is the tool that will be used to intersect \a mesh2D.
8826  * \param [in] eps - precision used to perform intersections and localization operations.
8827  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
8828  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
8829  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
8830  *                               So this array has a number of tuples equal to the number of cells of \a splitMesh2D and a number of component equal to 1.
8831  * \param [out] cellIdInMesh1D - the array that gives for each cell id \a i in \a splitMesh1D the 1 or 2 id(s) in \a splitMesh2D that \a i shares.
8832  *                               So this array has a number of tuples equal to the number of cells of \a splitMesh1D and a number of components equal to 2.
8833  */
8834 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
8835 {
8836   if(!mesh2D || !mesh1D)
8837     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
8838   mesh2D->checkFullyDefined();
8839   mesh1D->checkFullyDefined();
8840   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
8841     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
8842   // Step 1: compute all edge intersections (new nodes)
8843   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8844   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8845   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8846   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8847   //
8848   // Build desc connectivity
8849   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
8850   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8851   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
8852   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo);
8853   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8854   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
8855   // Step 2: re-order newly created nodes according to the ordering found in m2
8856   std::vector< std::vector<int> > intersectEdge2;
8857   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
8858   subDiv2.clear();
8859   //
8860   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo));
8861   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1->getBarycenterAndOwner());
8862   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
8863   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
8864   splitMesh1D=ret1.retn();
8865 }
8866
8867 /**
8868  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
8869  * (newly created) nodes corresponding to the edge intersections.
8870  * Output params:
8871  * @param[out] cr, crI connectivity of the resulting mesh
8872  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
8873  * TODO: describe input parameters
8874  */
8875 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8876                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8877                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8878                                                          const std::vector<double>& addCoords,
8879                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8880 {
8881   static const int SPACEDIM=2;
8882   const double *coo1(m1->getCoords()->getConstPointer());
8883   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
8884   int offset1(m1->getNumberOfNodes());
8885   const double *coo2(m2->getCoords()->getConstPointer());
8886   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
8887   int offset2(offset1+m2->getNumberOfNodes());
8888   int offset3(offset2+((int)addCoords.size())/2);
8889   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8890   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8891   // Here a BBTree on 2D-cells, not on segments:
8892   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8893   int ncell1(m1->getNumberOfCells());
8894   crI.push_back(0);
8895   for(int i=0;i<ncell1;i++)
8896     {
8897       std::vector<int> candidates2;
8898       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8899       std::map<INTERP_KERNEL::Node *,int> mapp;
8900       std::map<int,INTERP_KERNEL::Node *> mappRev;
8901       INTERP_KERNEL::QuadraticPolygon pol1;
8902       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8903       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8904       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
8905       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8906       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
8907       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8908           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8909       //
8910       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
8911       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8912       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8913       for(it1.first();!it1.finished();it1.next())
8914         edges1.insert(it1.current()->getPtr());
8915       //
8916       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
8917       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8918       int ii=0;
8919       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8920         {
8921           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8922           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8923           // Complete mapping with elements coming from the current cell it2 in mesh2:
8924           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8925           // pol2 is the new QP in the final merged result.
8926           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8927               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
8928         }
8929       ii=0;
8930       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8931         {
8932           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
8933           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8934           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8935           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8936         }
8937       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
8938       // by m2 but that we still want to keep in the final result.
8939       if(!edges1.empty())
8940         {
8941           try
8942           {
8943               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8944           }
8945           catch(INTERP_KERNEL::Exception& e)
8946           {
8947               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();
8948               throw INTERP_KERNEL::Exception(oss.str().c_str());
8949           }
8950         }
8951       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8952         (*it).second->decrRef();
8953     }
8954 }
8955
8956 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8957 {
8958   std::map<INTERP_KERNEL::Node *,int>::const_iterator it(m.find(n));
8959   if(it==m.end())
8960     throw INTERP_KERNEL::Exception("Internal error in remapping !");
8961   int v((*it).second);
8962   if(v==forbVal0 || v==forbVal1)
8963     return ;
8964   if(std::find(isect.begin(),isect.end(),v)==isect.end())
8965     isect.push_back(v);
8966 }
8967
8968 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8969 {
8970   int sz(c.size());
8971   if(sz<=1)
8972     return false;
8973   bool presenceOfOn(false);
8974   for(int i=0;i<sz;i++)
8975     {
8976       INTERP_KERNEL::ElementaryEdge *e(c[i]);
8977       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
8978         continue ;
8979       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
8980       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
8981     }
8982   return presenceOfOn;
8983 }
8984
8985 /**
8986  * 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.
8987  * 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.
8988  * 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.
8989  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
8990  *
8991  * \return int - the number of new nodes created (in most of cases 0).
8992  * 
8993  * \throw If \a this is not coherent.
8994  * \throw If \a this has not spaceDim equal to 2.
8995  * \throw If \a this has not meshDim equal to 2.
8996  * \throw If some subcells needed to be split are orphan.
8997  * \sa MEDCouplingUMesh::conformize2D
8998  */
8999 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
9000 {
9001   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
9002     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
9003   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
9004   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9005     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9006   if(midOpt==0 && midOptI==0)
9007     {
9008       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
9009       return 0;
9010     }
9011   else if(midOpt!=0 && midOptI!=0)
9012     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
9013   else
9014     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
9015 }
9016
9017 /*!
9018  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
9019  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
9020  * 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
9021  * will suppress such edges to use sub edges in \a this. So this method does not add nodes in \a this if merged edges are both linear (INTERP_KERNEL::NORM_SEG2).
9022  * In the other cases new nodes can be created. If any are created, they will be appended at the end of the coordinates object before the invokation of this method.
9023  * 
9024  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
9025  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
9026  *
9027  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
9028  * This method expects that all nodes in \a this are not closer than \a eps.
9029  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
9030  * 
9031  * \param [in] eps the relative error to detect merged edges.
9032  * \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
9033  *                           that the user is expected to deal with.
9034  *
9035  * \throw If \a this is not coherent.
9036  * \throw If \a this has not spaceDim equal to 2.
9037  * \throw If \a this has not meshDim equal to 2.
9038  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
9039  */
9040 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
9041 {
9042   static const int SPACEDIM=2;
9043   checkCoherency();
9044   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9045     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9046   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
9047   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
9048   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
9049   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
9050   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
9051   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
9052   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
9053   std::vector<double> addCoo;
9054   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
9055   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9056   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9057   for(int i=0;i<nDescCell;i++)
9058     {
9059       std::vector<int> candidates;
9060       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
9061       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9062         if(*it>i)
9063           {
9064             std::map<INTERP_KERNEL::Node *,int> m;
9065             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
9066                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
9067             INTERP_KERNEL::MergePoints merge;
9068             INTERP_KERNEL::QuadraticPolygon c1,c2;
9069             e1->intersectWith(e2,merge,c1,c2);
9070             e1->decrRef(); e2->decrRef();
9071             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
9072               overlapEdge[i].push_back(*it);
9073             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
9074               overlapEdge[*it].push_back(i);
9075             for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
9076               (*it2).first->decrRef();
9077           }
9078     }
9079   // splitting done. sort intersect point in intersectEdge.
9080   std::vector< std::vector<int> > middle(nDescCell);
9081   int nbOf2DCellsToBeSplit(0);
9082   bool middleNeedsToBeUsed(false);
9083   std::vector<bool> cells2DToTreat(nDescCell,false);
9084   for(int i=0;i<nDescCell;i++)
9085     {
9086       std::vector<int>& isect(intersectEdge[i]);
9087       int sz((int)isect.size());
9088       if(sz>1)
9089         {
9090           std::map<INTERP_KERNEL::Node *,int> m;
9091           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
9092           e->sortSubNodesAbs(coords,isect);
9093           e->decrRef();
9094           for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
9095             (*it2).first->decrRef();
9096         }
9097       if(sz!=0)
9098         {
9099           int idx0(rdi[i]),idx1(rdi[i+1]);
9100           if(idx1-idx0!=1)
9101             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
9102           if(!cells2DToTreat[rd[idx0]])
9103             {
9104               cells2DToTreat[rd[idx0]]=true;
9105               nbOf2DCellsToBeSplit++;
9106             }
9107           // try to reuse at most eventual 'middle' of SEG3
9108           std::vector<int>& mid(middle[i]);
9109           mid.resize(sz+1,-1);
9110           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
9111             {
9112               middleNeedsToBeUsed=true;
9113               const std::vector<int>& candidates(overlapEdge[i]);
9114               std::vector<int> trueCandidates;
9115               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
9116                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
9117                   trueCandidates.push_back(*itc);
9118               int stNode(c[ci[i]+1]),endNode(isect[0]);
9119               for(int j=0;j<sz+1;j++)
9120                 {
9121                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
9122                     {
9123                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
9124                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
9125                         { mid[j]=*itc; break; }
9126                     }
9127                   stNode=endNode;
9128                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
9129                 }
9130             }
9131         }
9132     }
9133   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
9134   if(nbOf2DCellsToBeSplit==0)
9135     return ret.retn();
9136   //
9137   int *retPtr(ret->getPointer());
9138   for(int i=0;i<nCell;i++)
9139     if(cells2DToTreat[i])
9140       *retPtr++=i;
9141   //
9142   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
9143   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
9144   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
9145   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
9146   if(middleNeedsToBeUsed)
9147     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
9148   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
9149   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
9150   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.
9151   setPartOfMySelf(ret->begin(),ret->end(),*modif);
9152   {
9153     bool areNodesMerged; int newNbOfNodes;
9154     if(nbOfNodesCreated!=0)
9155       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
9156   }
9157   return ret.retn();
9158 }
9159
9160 /*!
9161  * 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.
9162  * 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).
9163  * 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
9164  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
9165  * 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
9166  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
9167  *
9168  * 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
9169  * using new instance, idem for coordinates.
9170  *
9171  * 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.
9172  * 
9173  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
9174  *
9175  * \throw If \a this is not coherent.
9176  * \throw If \a this has not spaceDim equal to 2.
9177  * \throw If \a this has not meshDim equal to 2.
9178  * 
9179  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
9180  */
9181 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
9182 {
9183   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
9184   checkCoherency();
9185   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9186     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9187   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9188   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9189   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
9190   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
9191   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
9192   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
9193   const double *coords(_coords->begin());
9194   int *newciptr(newci->getPointer());
9195   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
9196     {
9197       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
9198         ret->pushBackSilent(i);
9199       newciptr[1]=newc->getNumberOfTuples();
9200     }
9201   //
9202   if(ret->empty())
9203     return ret.retn();
9204   if(!appendedCoords->empty())
9205     {
9206       appendedCoords->rearrange(2);
9207       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
9208       //non const part
9209       setCoords(newCoords);
9210     }
9211   //non const part
9212   setConnectivity(newc,newci,true);
9213   return ret.retn();
9214 }
9215
9216 /*!
9217  * \param [out] intersectEdge1 - for each cell in \a m1Desc returns the result of the split. The result is given using pair of int given resp start and stop.
9218  *                               So for all edge \a i in \a m1Desc \a  intersectEdge1[i] is of length 2*n where n is the number of sub edges.
9219  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
9220  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
9221  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
9222  * \param [out] addCoo - nodes to be append at the end
9223  */
9224 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
9225                                          std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2, std::vector<double>& addCoo)
9226 {
9227   static const int SPACEDIM=2;
9228   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9229   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9230   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
9231   // Build BB tree of all edges in the tool mesh (second mesh)
9232   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
9233   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9234   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
9235   intersectEdge1.resize(nDescCell1);
9236   colinear2.resize(nDescCell2);
9237   subDiv2.resize(nDescCell2);
9238   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
9239
9240   std::vector<int> candidates1(1);
9241   int offset1(m1Desc->getNumberOfNodes());
9242   int offset2(offset1+m2Desc->getNumberOfNodes());
9243   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
9244     {
9245       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
9246       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9247       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
9248         {
9249           std::map<INTERP_KERNEL::Node *,int> map1,map2;
9250           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
9251           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
9252           candidates1[0]=i;
9253           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
9254           // 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
9255           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
9256           std::set<INTERP_KERNEL::Node *> nodes;
9257           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
9258           std::size_t szz(nodes.size());
9259           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
9260           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
9261           for(std::size_t iii=0;iii<szz;iii++,itt++)
9262             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
9263           // end of protection
9264           // Performs egde cutting:
9265           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
9266           delete pol2;
9267           delete pol1;
9268         }
9269       else
9270         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
9271     }
9272 }
9273
9274 /*!
9275  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
9276  * It builds the descending connectivity of the two meshes, and then using a binary tree
9277  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
9278  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
9279  */
9280 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
9281                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
9282                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
9283                                                    std::vector<double>& addCoo,
9284                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
9285 {
9286   // Build desc connectivity
9287   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
9288   desc2=DataArrayInt::New();
9289   descIndx2=DataArrayInt::New();
9290   revDesc2=DataArrayInt::New();
9291   revDescIndx2=DataArrayInt::New();
9292   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9293   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
9294   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
9295   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
9296   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
9297   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo);
9298   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
9299   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
9300 }
9301
9302 /*!
9303  * This method performs the 2nd step of Partition of 2D mesh.
9304  * This method has 4 inputs :
9305  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
9306  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
9307  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
9308  * 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'
9309  * Nodes end up lying consecutively on a cutted edge.
9310  * \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.
9311  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
9312  * \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.
9313  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
9314  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
9315  */
9316 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9317                                            const std::vector<double>& addCoo,
9318                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
9319 {
9320   int offset1=m1->getNumberOfNodes();
9321   int ncell=m2->getNumberOfCells();
9322   const int *c=m2->getNodalConnectivity()->getConstPointer();
9323   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
9324   const double *coo=m2->getCoords()->getConstPointer();
9325   const double *cooBis=m1->getCoords()->getConstPointer();
9326   int offset2=offset1+m2->getNumberOfNodes();
9327   intersectEdge.resize(ncell);
9328   for(int i=0;i<ncell;i++,cI++)
9329     {
9330       const std::vector<int>& divs=subDiv[i];
9331       int nnode=cI[1]-cI[0]-1;
9332       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
9333       std::map<INTERP_KERNEL::Node *, int> mapp22;
9334       for(int j=0;j<nnode;j++)
9335         {
9336           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
9337           int nnid=c[(*cI)+j+1];
9338           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
9339           mapp22[nn]=nnid+offset1;
9340         }
9341       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
9342       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
9343         ((*it).second.first)->decrRef();
9344       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
9345       std::map<INTERP_KERNEL::Node *,int> mapp3;
9346       for(std::size_t j=0;j<divs.size();j++)
9347         {
9348           int id=divs[j];
9349           INTERP_KERNEL::Node *tmp=0;
9350           if(id<offset1)
9351             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
9352           else if(id<offset2)
9353             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
9354           else
9355             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
9356           addNodes[j]=tmp;
9357           mapp3[tmp]=id;
9358         }
9359       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
9360       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
9361         (*it)->decrRef();
9362       e->decrRef();
9363     }
9364 }
9365
9366 /*!
9367  * 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).
9368  * 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
9369  * with a plane. The result will be put in 'cut3DSuf' out parameter.
9370  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
9371  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
9372  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
9373  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
9374  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
9375  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
9376  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
9377  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
9378  * \param [out] cut3DSuf input/output param.
9379  */
9380 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
9381                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
9382                                                    const int *desc, const int *descIndx, 
9383                                                    std::vector< std::pair<int,int> >& cut3DSurf)
9384 {
9385   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
9386   int nbOf3DSurfCell=(int)cut3DSurf.size();
9387   for(int i=0;i<nbOf3DSurfCell;i++)
9388     {
9389       std::vector<int> res;
9390       int offset=descIndx[i];
9391       int nbOfSeg=descIndx[i+1]-offset;
9392       for(int j=0;j<nbOfSeg;j++)
9393         {
9394           int edgeId=desc[offset+j];
9395           int status=cut3DCurve[edgeId];
9396           if(status!=-2)
9397             {
9398               if(status>-1)
9399                 res.push_back(status);
9400               else
9401                 {
9402                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
9403                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
9404                 }
9405             }
9406         }
9407       switch(res.size())
9408       {
9409         case 2:
9410           {
9411             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9412             break;
9413           }
9414         case 1:
9415         case 0:
9416           {
9417             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
9418             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
9419             if(res.size()==2)
9420               {
9421                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9422               }
9423             else
9424               {
9425                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
9426               }
9427             break;
9428           }
9429         default:
9430           {// case when plane is on a multi colinear edge of a polyhedron
9431             if((int)res.size()==2*nbOfSeg)
9432               {
9433                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
9434               }
9435             else
9436               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
9437           }
9438       }
9439     }
9440 }
9441
9442 /*!
9443  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
9444  * 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).
9445  * 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
9446  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
9447  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
9448  * \param desc is the descending connectivity 3D->3DSurf
9449  * \param descIndx is the descending connectivity index 3D->3DSurf
9450  */
9451 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
9452                                                   const int *desc, const int *descIndx,
9453                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
9454 {
9455   checkFullyDefined();
9456   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9457     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
9458   const int *nodal3D=_nodal_connec->getConstPointer();
9459   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
9460   int nbOfCells=getNumberOfCells();
9461   for(int i=0;i<nbOfCells;i++)
9462     {
9463       std::map<int, std::set<int> > m;
9464       int offset=descIndx[i];
9465       int nbOfFaces=descIndx[i+1]-offset;
9466       int start=-1;
9467       int end=-1;
9468       for(int j=0;j<nbOfFaces;j++)
9469         {
9470           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
9471           if(p.first!=-1 && p.second!=-1)
9472             {
9473               if(p.first!=-2)
9474                 {
9475                   start=p.first; end=p.second;
9476                   m[p.first].insert(p.second);
9477                   m[p.second].insert(p.first);
9478                 }
9479               else
9480                 {
9481                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
9482                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
9483                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
9484                   INTERP_KERNEL::NormalizedCellType cmsId;
9485                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
9486                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
9487                   for(unsigned k=0;k<nbOfNodesSon;k++)
9488                     {
9489                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
9490                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
9491                     }
9492                 }
9493             }
9494         }
9495       if(m.empty())
9496         continue;
9497       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
9498       int prev=end;
9499       while(end!=start)
9500         {
9501           std::map<int, std::set<int> >::const_iterator it=m.find(start);
9502           const std::set<int>& s=(*it).second;
9503           std::set<int> s2; s2.insert(prev);
9504           std::set<int> s3;
9505           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
9506           if(s3.size()==1)
9507             {
9508               int val=*s3.begin();
9509               conn.push_back(start);
9510               prev=start;
9511               start=val;
9512             }
9513           else
9514             start=end;
9515         }
9516       conn.push_back(end);
9517       if(conn.size()>3)
9518         {
9519           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
9520           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
9521           cellIds->pushBackSilent(i);
9522         }
9523     }
9524 }
9525
9526 /*!
9527  * 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
9528  * 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
9529  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
9530  * 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
9531  * 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.
9532  * 
9533  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
9534  */
9535 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
9536 {
9537   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
9538   if(sz>=4)
9539     {
9540       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
9541       if(cm.getDimension()==2)
9542         {
9543           const int *node=nodalConnBg+1;
9544           int startNode=*node++;
9545           double refX=coords[2*startNode];
9546           for(;node!=nodalConnEnd;node++)
9547             {
9548               if(coords[2*(*node)]<refX)
9549                 {
9550                   startNode=*node;
9551                   refX=coords[2*startNode];
9552                 }
9553             }
9554           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
9555           refX=1e300;
9556           double tmp1;
9557           double tmp2[2];
9558           double angle0=-M_PI/2;
9559           //
9560           int nextNode=-1;
9561           int prevNode=-1;
9562           double resRef;
9563           double angleNext=0.;
9564           while(nextNode!=startNode)
9565             {
9566               nextNode=-1;
9567               resRef=1e300;
9568               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
9569                 {
9570                   if(*node!=tmpOut.back() && *node!=prevNode)
9571                     {
9572                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
9573                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
9574                       double res;
9575                       if(angleM<=angle0)
9576                         res=angle0-angleM;
9577                       else
9578                         res=angle0-angleM+2.*M_PI;
9579                       if(res<resRef)
9580                         {
9581                           nextNode=*node;
9582                           resRef=res;
9583                           angleNext=angleM;
9584                         }
9585                     }
9586                 }
9587               if(nextNode!=startNode)
9588                 {
9589                   angle0=angleNext-M_PI;
9590                   if(angle0<-M_PI)
9591                     angle0+=2*M_PI;
9592                   prevNode=tmpOut.back();
9593                   tmpOut.push_back(nextNode);
9594                 }
9595             }
9596           std::vector<int> tmp3(2*(sz-1));
9597           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
9598           std::copy(nodalConnBg+1,nodalConnEnd,it);
9599           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
9600             {
9601               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9602               return false;
9603             }
9604           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
9605             {
9606               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9607               return false;
9608             }
9609           else
9610             {
9611               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
9612               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
9613               return true;
9614             }
9615         }
9616       else
9617         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9618     }
9619   else
9620     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9621 }
9622
9623 /*!
9624  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
9625  * 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.
9626  * 
9627  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
9628  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
9629  * \param [in,out] arr array in which the remove operation will be done.
9630  * \param [in,out] arrIndx array in the remove operation will modify
9631  * \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])
9632  * \return true if \b arr and \b arrIndx have been modified, false if not.
9633  */
9634 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
9635 {
9636   if(!arrIndx || !arr)
9637     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
9638   if(offsetForRemoval<0)
9639     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
9640   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
9641   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
9642   int *arrIPtr=arrIndx->getPointer();
9643   *arrIPtr++=0;
9644   int previousArrI=0;
9645   const int *arrPtr=arr->getConstPointer();
9646   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
9647   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
9648     {
9649       if(*arrIPtr-previousArrI>offsetForRemoval)
9650         {
9651           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
9652             {
9653               if(s.find(*work)==s.end())
9654                 arrOut.push_back(*work);
9655             }
9656         }
9657       previousArrI=*arrIPtr;
9658       *arrIPtr=(int)arrOut.size();
9659     }
9660   if(arr->getNumberOfTuples()==(int)arrOut.size())
9661     return false;
9662   arr->alloc((int)arrOut.size(),1);
9663   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
9664   return true;
9665 }
9666
9667 /*!
9668  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9669  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
9670  * The selection of extraction is done standardly in new2old format.
9671  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9672  *
9673  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9674  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9675  * \param [in] arrIn arr origin array from which the extraction will be done.
9676  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9677  * \param [out] arrOut the resulting array
9678  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9679  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
9680  */
9681 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9682                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
9683 {
9684   if(!arrIn || !arrIndxIn)
9685     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
9686   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9687   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9688     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
9689   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
9690   const int *arrInPtr=arrIn->getConstPointer();
9691   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9692   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9693   if(nbOfGrps<0)
9694     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9695   int maxSizeOfArr=arrIn->getNumberOfTuples();
9696   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9697   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9698   arrIo->alloc((int)(sz+1),1);
9699   const int *idsIt=idsOfSelectBg;
9700   int *work=arrIo->getPointer();
9701   *work++=0;
9702   int lgth=0;
9703   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
9704     {
9705       if(*idsIt>=0 && *idsIt<nbOfGrps)
9706         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
9707       else
9708         {
9709           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9710           throw INTERP_KERNEL::Exception(oss.str().c_str());
9711         }
9712       if(lgth>=work[-1])
9713         *work=lgth;
9714       else
9715         {
9716           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
9717           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
9718           throw INTERP_KERNEL::Exception(oss.str().c_str());
9719         }
9720     }
9721   arro->alloc(lgth,1);
9722   work=arro->getPointer();
9723   idsIt=idsOfSelectBg;
9724   for(std::size_t i=0;i<sz;i++,idsIt++)
9725     {
9726       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
9727         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
9728       else
9729         {
9730           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
9731           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9732           throw INTERP_KERNEL::Exception(oss.str().c_str());
9733         }
9734     }
9735   arrOut=arro.retn();
9736   arrIndexOut=arrIo.retn();
9737 }
9738
9739 /*!
9740  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9741  * 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 ).
9742  * The selection of extraction is done standardly in new2old format.
9743  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9744  *
9745  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9746  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9747  * \param [in] arrIn arr origin array from which the extraction will be done.
9748  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9749  * \param [out] arrOut the resulting array
9750  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9751  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
9752  */
9753 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9754                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
9755 {
9756   if(!arrIn || !arrIndxIn)
9757     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
9758   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9759   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9760     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
9761   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
9762   const int *arrInPtr=arrIn->getConstPointer();
9763   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9764   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9765   if(nbOfGrps<0)
9766     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9767   int maxSizeOfArr=arrIn->getNumberOfTuples();
9768   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9769   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9770   arrIo->alloc((int)(sz+1),1);
9771   int idsIt=idsOfSelectStart;
9772   int *work=arrIo->getPointer();
9773   *work++=0;
9774   int lgth=0;
9775   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
9776     {
9777       if(idsIt>=0 && idsIt<nbOfGrps)
9778         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
9779       else
9780         {
9781           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9782           throw INTERP_KERNEL::Exception(oss.str().c_str());
9783         }
9784       if(lgth>=work[-1])
9785         *work=lgth;
9786       else
9787         {
9788           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
9789           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
9790           throw INTERP_KERNEL::Exception(oss.str().c_str());
9791         }
9792     }
9793   arro->alloc(lgth,1);
9794   work=arro->getPointer();
9795   idsIt=idsOfSelectStart;
9796   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
9797     {
9798       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
9799         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
9800       else
9801         {
9802           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
9803           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9804           throw INTERP_KERNEL::Exception(oss.str().c_str());
9805         }
9806     }
9807   arrOut=arro.retn();
9808   arrIndexOut=arrIo.retn();
9809 }
9810
9811 /*!
9812  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9813  * 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
9814  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9815  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9816  *
9817  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9818  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9819  * \param [in] arrIn arr origin array from which the extraction will be done.
9820  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9821  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
9822  * \param [in] srcArrIndex index array of \b srcArr
9823  * \param [out] arrOut the resulting array
9824  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9825  * 
9826  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9827  */
9828 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9829                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9830                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
9831 {
9832   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9833     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9834   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9835   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9836   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9837   std::vector<bool> v(nbOfTuples,true);
9838   int offset=0;
9839   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9840   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9841   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9842     {
9843       if(*it>=0 && *it<nbOfTuples)
9844         {
9845           v[*it]=false;
9846           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9847         }
9848       else
9849         {
9850           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9851           throw INTERP_KERNEL::Exception(oss.str().c_str());
9852         }
9853     }
9854   srcArrIndexPtr=srcArrIndex->getConstPointer();
9855   arrIo->alloc(nbOfTuples+1,1);
9856   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9857   const int *arrInPtr=arrIn->getConstPointer();
9858   const int *srcArrPtr=srcArr->getConstPointer();
9859   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9860   int *arroPtr=arro->getPointer();
9861   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9862     {
9863       if(v[ii])
9864         {
9865           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9866           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9867         }
9868       else
9869         {
9870           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9871           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9872           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9873         }
9874     }
9875   arrOut=arro.retn();
9876   arrIndexOut=arrIo.retn();
9877 }
9878
9879 /*!
9880  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9881  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9882  *
9883  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9884  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9885  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9886  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9887  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
9888  * \param [in] srcArrIndex index array of \b srcArr
9889  * 
9890  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9891  */
9892 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9893                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
9894 {
9895   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9896     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9897   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9898   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9899   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9900   int *arrInOutPtr=arrInOut->getPointer();
9901   const int *srcArrPtr=srcArr->getConstPointer();
9902   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9903     {
9904       if(*it>=0 && *it<nbOfTuples)
9905         {
9906           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9907             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9908           else
9909             {
9910               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] !";
9911               throw INTERP_KERNEL::Exception(oss.str().c_str());
9912             }
9913         }
9914       else
9915         {
9916           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9917           throw INTERP_KERNEL::Exception(oss.str().c_str());
9918         }
9919     }
9920 }
9921
9922 /*!
9923  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9924  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9925  * 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]].
9926  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9927  * A negative value in \b arrIn means that it is ignored.
9928  * 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.
9929  * 
9930  * \param [in] arrIn arr origin array from which the extraction will be done.
9931  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9932  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9933  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9934  */
9935 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9936 {
9937   int seed=0,nbOfDepthPeelingPerformed=0;
9938   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9939 }
9940
9941 /*!
9942  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9943  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9944  * 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]].
9945  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9946  * A negative value in \b arrIn means that it is ignored.
9947  * 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.
9948  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9949  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9950  * \param [in] arrIn arr origin array from which the extraction will be done.
9951  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9952  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9953  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9954  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9955  * \sa MEDCouplingUMesh::partitionBySpreadZone
9956  */
9957 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9958 {
9959   nbOfDepthPeelingPerformed=0;
9960   if(!arrIndxIn)
9961     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9962   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9963   if(nbOfTuples<=0)
9964     {
9965       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9966       return ret;
9967     }
9968   //
9969   std::vector<bool> fetched(nbOfTuples,false);
9970   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9971 }
9972
9973 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9974 {
9975   nbOfDepthPeelingPerformed=0;
9976   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9977     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9978   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9979   std::vector<bool> fetched2(nbOfTuples,false);
9980   int i=0;
9981   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9982     {
9983       if(*seedElt>=0 && *seedElt<nbOfTuples)
9984         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9985       else
9986         { 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()); }
9987     }
9988   const int *arrInPtr=arrIn->getConstPointer();
9989   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9990   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9991   std::vector<int> idsToFetch1(seedBg,seedEnd);
9992   std::vector<int> idsToFetch2;
9993   std::vector<int> *idsToFetch=&idsToFetch1;
9994   std::vector<int> *idsToFetchOther=&idsToFetch2;
9995   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9996     {
9997       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9998         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9999           if(!fetched[*it2])
10000             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
10001       std::swap(idsToFetch,idsToFetchOther);
10002       idsToFetchOther->clear();
10003       nbOfDepthPeelingPerformed++;
10004     }
10005   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
10006   i=0;
10007   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
10008   int *retPtr=ret->getPointer();
10009   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
10010     if(*it)
10011       *retPtr++=i;
10012   return ret.retn();
10013 }
10014
10015 /*!
10016  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10017  * 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
10018  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10019  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10020  *
10021  * \param [in] start begin of set of ids of the input extraction (included)
10022  * \param [in] end end of set of ids of the input extraction (excluded)
10023  * \param [in] step step of the set of ids in range mode.
10024  * \param [in] arrIn arr origin array from which the extraction will be done.
10025  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10026  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10027  * \param [in] srcArrIndex index array of \b srcArr
10028  * \param [out] arrOut the resulting array
10029  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10030  * 
10031  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
10032  */
10033 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10034                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10035                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10036 {
10037   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10038     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
10039   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10040   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10041   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10042   int offset=0;
10043   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10044   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10045   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
10046   int it=start;
10047   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10048     {
10049       if(it>=0 && it<nbOfTuples)
10050         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
10051       else
10052         {
10053           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10054           throw INTERP_KERNEL::Exception(oss.str().c_str());
10055         }
10056     }
10057   srcArrIndexPtr=srcArrIndex->getConstPointer();
10058   arrIo->alloc(nbOfTuples+1,1);
10059   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10060   const int *arrInPtr=arrIn->getConstPointer();
10061   const int *srcArrPtr=srcArr->getConstPointer();
10062   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10063   int *arroPtr=arro->getPointer();
10064   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10065     {
10066       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
10067       if(pos<0)
10068         {
10069           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10070           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10071         }
10072       else
10073         {
10074           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10075           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10076         }
10077     }
10078   arrOut=arro.retn();
10079   arrIndexOut=arrIo.retn();
10080 }
10081
10082 /*!
10083  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10084  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10085  *
10086  * \param [in] start begin of set of ids of the input extraction (included)
10087  * \param [in] end end of set of ids of the input extraction (excluded)
10088  * \param [in] step step of the set of ids in range mode.
10089  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10090  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10091  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
10092  * \param [in] srcArrIndex index array of \b srcArr
10093  * 
10094  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10095  */
10096 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10097                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10098 {
10099   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10100     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
10101   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10102   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10103   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10104   int *arrInOutPtr=arrInOut->getPointer();
10105   const int *srcArrPtr=srcArr->getConstPointer();
10106   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
10107   int it=start;
10108   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
10109     {
10110       if(it>=0 && it<nbOfTuples)
10111         {
10112           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
10113             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
10114           else
10115             {
10116               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
10117               throw INTERP_KERNEL::Exception(oss.str().c_str());
10118             }
10119         }
10120       else
10121         {
10122           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10123           throw INTERP_KERNEL::Exception(oss.str().c_str());
10124         }
10125     }
10126 }
10127
10128 /*!
10129  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
10130  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
10131  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
10132  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
10133  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
10134  * 
10135  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
10136  */
10137 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
10138 {
10139   checkFullyDefined();
10140   int mdim=getMeshDimension();
10141   int spaceDim=getSpaceDimension();
10142   if(mdim!=spaceDim)
10143     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
10144   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
10145   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
10146   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
10147   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
10148   ret->setCoords(getCoords());
10149   ret->allocateCells((int)partition.size());
10150   //
10151   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
10152     {
10153       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
10154       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
10155       switch(mdim)
10156       {
10157         case 2:
10158           cell=tmp->buildUnionOf2DMesh();
10159           break;
10160         case 3:
10161           cell=tmp->buildUnionOf3DMesh();
10162           break;
10163         default:
10164           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
10165       }
10166
10167       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
10168     }
10169   //
10170   ret->finishInsertingCells();
10171   return ret.retn();
10172 }
10173
10174 /*!
10175  * This method partitions \b this into contiguous zone.
10176  * This method only needs a well defined connectivity. Coordinates are not considered here.
10177  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
10178  */
10179 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
10180 {
10181   int nbOfCellsCur=getNumberOfCells();
10182   std::vector<DataArrayInt *> ret;
10183   if(nbOfCellsCur<=0)
10184     return ret;
10185   DataArrayInt *neigh=0,*neighI=0;
10186   computeNeighborsOfCells(neigh,neighI);
10187   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
10188   std::vector<bool> fetchedCells(nbOfCellsCur,false);
10189   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
10190   int seed=0;
10191   while(seed<nbOfCellsCur)
10192     {
10193       int nbOfPeelPerformed=0;
10194       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
10195       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
10196     }
10197   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
10198     ret.push_back((*it).retn());
10199   return ret;
10200 }
10201
10202 /*!
10203  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
10204  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
10205  *
10206  * \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.
10207  * \return a newly allocated DataArrayInt to be managed by the caller.
10208  * \throw In case of \a code has not the right format (typically of size 3*n)
10209  */
10210 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
10211 {
10212   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
10213   std::size_t nb=code.size()/3;
10214   if(code.size()%3!=0)
10215     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
10216   ret->alloc((int)nb,2);
10217   int *retPtr=ret->getPointer();
10218   for(std::size_t i=0;i<nb;i++,retPtr+=2)
10219     {
10220       retPtr[0]=code[3*i+2];
10221       retPtr[1]=code[3*i+2]+code[3*i+1];
10222     }
10223   return ret.retn();
10224 }
10225
10226 /*!
10227  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
10228  * All cells in \a this are expected to be linear 3D cells.
10229  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
10230  * It leads to an increase to number of cells.
10231  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
10232  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
10233  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
10234  *
10235  * \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.
10236  *                      For all other cells, the splitting policy will be ignored.
10237  * \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. 
10238  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
10239  *          an id of old cell producing it. The caller is to delete this array using
10240  *         decrRef() as it is no more needed.
10241  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
10242  *
10243  * \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
10244  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
10245  * 
10246  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
10247  * \throw If \a this is not fully constituted with linear 3D cells.
10248  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
10249  */
10250 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
10251 {
10252   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
10253   checkConnectivityFullyDefined();
10254   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10255     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
10256   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
10257   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
10258   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
10259   int *retPt(ret->getPointer());
10260   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
10261   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
10262   const int *oldc(_nodal_connec->begin());
10263   const int *oldci(_nodal_connec_index->begin());
10264   const double *coords(_coords->begin());
10265   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
10266     {
10267       std::vector<int> a; std::vector<double> b;
10268       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
10269       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
10270       const int *aa(&a[0]);
10271       if(!b.empty())
10272         {
10273           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
10274             if(*it<0)
10275               *it=(-(*(it))-1+nbNodes);
10276           addPts->insertAtTheEnd(b.begin(),b.end());
10277           nbNodes+=(int)b.size()/3;
10278         }
10279       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
10280         newConn->insertAtTheEnd(aa,aa+4);
10281     }
10282   if(!addPts->empty())
10283     {
10284       addPts->rearrange(3);
10285       nbOfAdditionalPoints=addPts->getNumberOfTuples();
10286       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
10287       ret0->setCoords(addPts);
10288     }
10289   else
10290     {
10291       nbOfAdditionalPoints=0;
10292       ret0->setCoords(getCoords());
10293     }
10294   ret0->setNodalConnectivity(newConn);
10295   //
10296   ret->computeOffsets2();
10297   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
10298   return ret0.retn();
10299 }
10300
10301 /*!
10302  * 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). 
10303  *
10304  * \sa MEDCouplingUMesh::split2DCells
10305  */
10306 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
10307 {
10308   checkConnectivityFullyDefined();
10309   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
10310   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10311   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10312   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10313   int prevPosOfCi(ciPtr[0]);
10314   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10315     {
10316       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
10317       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
10318       for(int j=0;j<sz;j++)
10319         {
10320           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
10321           for(int k=0;k<sz2;k++)
10322             *cPtr++=subPtr[offset2+k];
10323           if(j!=sz-1)
10324             *cPtr++=oldConn[prevPosOfCi+j+2];
10325           deltaSz+=sz2;
10326         }
10327       prevPosOfCi=ciPtr[1];
10328       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10329     }
10330   if(c->end()!=cPtr)
10331     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
10332   _nodal_connec->decrRef();
10333   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
10334 }
10335
10336 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
10337 {
10338   if(id!=-1)
10339     return id;
10340   else
10341     {
10342       int ret(nodesCnter++);
10343       double newPt[2];
10344       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
10345       addCoo.insertAtTheEnd(newPt,newPt+2);
10346       return ret;
10347     }
10348 }
10349
10350 /// @cond INTERNAL
10351
10352 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)
10353 {
10354   int tmp[3];
10355   int trueStart(start>=0?start:nbOfEdges+start);
10356   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
10357   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
10358   if(linOrArc)
10359     {
10360       if(stp-start>1)
10361         {
10362           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10363           InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
10364           middles.push_back(tmp3+offset);
10365         }
10366       else
10367         middles.push_back(connBg[trueStart+nbOfEdges]);
10368     }
10369 }
10370
10371 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)
10372 {
10373   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
10374   newConnOfCell->pushBackSilent(tmpEnd);
10375   if(linOrArc)
10376     {
10377       if(stp-start>1)
10378         {
10379           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10380           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
10381           middles.push_back(tmp3+offset);
10382         }
10383       else
10384         middles.push_back(connBg[start+nbOfEdges]);
10385     }
10386 }
10387
10388 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)
10389 {
10390   if(linOrArc)
10391     {
10392       if(stp-start>1)
10393         {
10394           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
10395           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10396           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
10397           middles.push_back(tmp3+offset);
10398         }
10399       else
10400         middles.push_back(connBg[start+nbOfEdges]);
10401     }
10402 }
10403
10404 /// @cond INTERNAL
10405
10406 /*!
10407  * 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 ) .
10408  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
10409  */
10410 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
10411 {
10412   std::size_t sz(std::distance(connBg,connEnd));
10413   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
10414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
10415   sz--;
10416   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
10417   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
10418   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
10419   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
10420   INTERP_KERNEL::NormalizedCellType typeOfSon;
10421   std::vector<int> middles;
10422   bool ret(false);
10423   for(;nbOfHit<nbs;nbOfTurn++)
10424     {
10425       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
10426       std::map<INTERP_KERNEL::Node *,int> m;
10427       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
10428       posEndElt++;
10429       nbOfHit++;
10430       unsigned endI(nbs-nbOfHit);
10431       for(unsigned i=0;i<endI;i++)
10432         {
10433           cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
10434           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
10435           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
10436           bool isColinear(eint->areColinears());
10437           if(isColinear)
10438             {
10439               nbOfHit++;
10440               posEndElt++;
10441               ret=true;
10442             }
10443           delete eint;
10444           eCand->decrRef();
10445           if(!isColinear)
10446             {
10447               if(nbOfTurn==0)
10448                 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
10449                   unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
10450                   for(unsigned ii=0;ii<endII;ii++)
10451                     {
10452                       cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
10453                       eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
10454                       eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
10455                       isColinear=eint->areColinears();
10456                       if(isColinear)
10457                         {
10458                           nbOfHit++;
10459                           posBaseElt--;
10460                           ret=true;
10461                         }
10462                       delete eint;
10463                       eCand->decrRef();
10464                       if(!isColinear)
10465                         break;
10466                     }
10467                 }
10468               break;
10469             }
10470         }
10471       //push [posBaseElt,posEndElt) in newConnOfCell using e
10472       if(nbOfTurn==0)
10473         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10474       else if(nbOfHit!=nbs)
10475         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10476       else
10477         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10478       posBaseElt=posEndElt;
10479       for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it=m.begin();it!=m.end();it++)
10480         (*it).first->decrRef();
10481       e->decrRef();
10482     }
10483   if(!middles.empty())
10484     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
10485   return ret;
10486 }
10487
10488 /*!
10489  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
10490  *
10491  * \return  int - the number of new nodes created.
10492  * \sa MEDCouplingUMesh::split2DCells
10493  */
10494 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
10495 {
10496   checkCoherency();
10497   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
10498   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10499   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
10500   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10501   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
10502   const double *oldCoordsPtr(getCoords()->begin());
10503   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10504   int prevPosOfCi(ciPtr[0]);
10505   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10506     {
10507       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
10508       for(int j=0;j<sz;j++)
10509         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
10510       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
10511       for(int j=0;j<sz;j++)//loop over subedges of oldConn
10512         {
10513           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
10514           if(sz2==0)
10515             {
10516               if(j<sz-1)
10517                 cPtr[1]=oldConn[prevPosOfCi+2+j];
10518               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
10519               continue;
10520             }
10521           std::vector<INTERP_KERNEL::Node *> ns(3);
10522           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
10523           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
10524           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
10525           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
10526           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
10527             {
10528               cPtr[1]=subPtr[offset2+k];
10529               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
10530             }
10531           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
10532           if(j!=sz-1)
10533             { cPtr[1]=tmpEnd; }
10534           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
10535         }
10536       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
10537       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10538     }
10539   if(c->end()!=cPtr)
10540     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
10541   _nodal_connec->decrRef();
10542   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
10543   addCoo->rearrange(2);
10544   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
10545   setCoords(coo);
10546   return addCoo->getNumberOfTuples();
10547 }
10548
10549 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
10550     _own_cell(true),_cell_id(-1),_nb_cell(0)
10551 {
10552   if(mesh)
10553     {
10554       mesh->incrRef();
10555       _nb_cell=mesh->getNumberOfCells();
10556     }
10557 }
10558
10559 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
10560 {
10561   if(_mesh)
10562     _mesh->decrRef();
10563   if(_own_cell)
10564     delete _cell;
10565 }
10566
10567 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
10568     _own_cell(false),_cell_id(bg-1),
10569     _nb_cell(end)
10570 {
10571   if(mesh)
10572     mesh->incrRef();
10573 }
10574
10575 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
10576 {
10577   _cell_id++;
10578   if(_cell_id<_nb_cell)
10579     {
10580       _cell->next();
10581       return _cell;
10582     }
10583   else
10584     return 0;
10585 }
10586
10587 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
10588 {
10589   if(_mesh)
10590     _mesh->incrRef();
10591 }
10592
10593 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
10594 {
10595   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
10596 }
10597
10598 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
10599 {
10600   if(_mesh)
10601     _mesh->decrRef();
10602 }
10603
10604 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
10605     _itc(itc),
10606     _bg(bg),_end(end)
10607 {
10608   if(_mesh)
10609     _mesh->incrRef();
10610 }
10611
10612 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
10613 {
10614   if(_mesh)
10615     _mesh->decrRef();
10616 }
10617
10618 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
10619 {
10620   return _type;
10621 }
10622
10623 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
10624 {
10625   return _end-_bg;
10626 }
10627
10628 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
10629 {
10630   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
10631 }
10632
10633 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
10634 {
10635   if(mesh)
10636     {
10637       mesh->incrRef();
10638       _nb_cell=mesh->getNumberOfCells();
10639     }
10640 }
10641
10642 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
10643 {
10644   if(_mesh)
10645     _mesh->decrRef();
10646   delete _cell;
10647 }
10648
10649 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
10650 {
10651   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
10652   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
10653   if(_cell_id<_nb_cell)
10654     {
10655       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
10656       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
10657       int startId=_cell_id;
10658       _cell_id+=nbOfElems;
10659       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
10660     }
10661   else
10662     return 0;
10663 }
10664
10665 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
10666 {
10667   if(mesh)
10668     {
10669       _conn=mesh->getNodalConnectivity()->getPointer();
10670       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
10671     }
10672 }
10673
10674 void MEDCouplingUMeshCell::next()
10675 {
10676   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10677     {
10678       _conn+=_conn_lgth;
10679       _conn_indx++;
10680     }
10681   _conn_lgth=_conn_indx[1]-_conn_indx[0];
10682 }
10683
10684 std::string MEDCouplingUMeshCell::repr() const
10685 {
10686   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10687     {
10688       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
10689       oss << " : ";
10690       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
10691       return oss.str();
10692     }
10693   else
10694     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
10695 }
10696
10697 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
10698 {
10699   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10700     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
10701   else
10702     return INTERP_KERNEL::NORM_ERROR;
10703 }
10704
10705 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
10706 {
10707   lgth=_conn_lgth;
10708   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10709     return _conn;
10710   else
10711     return 0;
10712 }