Salome HOME
Retrieve refactor from abn/intersect_1D
[modules/med.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
42
43 #include <sstream>
44 #include <fstream>
45 #include <numeric>
46 #include <cstring>
47 #include <limits>
48 #include <list>
49
50 using namespace ParaMEDMEM;
51
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53
54 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
55
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 {
58   return new MEDCouplingUMesh;
59 }
60
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
62 {
63   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64   ret->setName(meshName);
65   ret->setMeshDimension(meshDim);
66   return ret;
67 }
68
69 /*!
70  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71  * between \a this and the new mesh.
72  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73  *          delete this mesh using decrRef() as it is no more needed. 
74  */
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
76 {
77   return clone(true);
78 }
79
80 /*!
81  * Returns a new MEDCouplingMesh which is a copy of \a this one.
82  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83  * this mesh are shared by the new mesh.
84  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85  *          delete this mesh using decrRef() as it is no more needed. 
86  */
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
88 {
89   return new MEDCouplingUMesh(*this,recDeepCpy);
90 }
91
92 /*!
93  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94  * The coordinates are shared between \a this and the returned instance.
95  * 
96  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97  * \sa MEDCouplingUMesh::deepCpy
98  */
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
100 {
101   checkConnectivityFullyDefined();
102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104   ret->setConnectivity(c,ci);
105   return ret.retn();
106 }
107
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
109 {
110   if(!other)
111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
113   if(!otherC)
114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
117 }
118
119 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
120 {
121   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
122   return ret;
123 }
124
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildren() const
126 {
127   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildren());
128   if(_nodal_connec)
129     ret.push_back(_nodal_connec);
130   if(_nodal_connec_index)
131     ret.push_back(_nodal_connec_index);
132   return ret;
133 }
134
135 void MEDCouplingUMesh::updateTime() const
136 {
137   MEDCouplingPointSet::updateTime();
138   if(_nodal_connec)
139     {
140       updateTimeWith(*_nodal_connec);
141     }
142   if(_nodal_connec_index)
143     {
144       updateTimeWith(*_nodal_connec_index);
145     }
146 }
147
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
149 {
150 }
151
152 /*!
153  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154  * then \a this mesh is most probably is writable, exchangeable and available for most
155  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156  * this method to check that all is in order with \a this mesh.
157  *  \throw If the mesh dimension is not set.
158  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
159  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160  *  \throw If the connectivity data array has more than one component.
161  *  \throw If the connectivity data array has a named component.
162  *  \throw If the connectivity index data array has more than one component.
163  *  \throw If the connectivity index data array has a named component.
164  */
165 void MEDCouplingUMesh::checkCoherency() const
166 {
167   if(_mesh_dim<-1)
168     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
169   if(_mesh_dim!=-1)
170     MEDCouplingPointSet::checkCoherency();
171   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
172     {
173       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
174         {
175           std::ostringstream message;
176           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177           throw INTERP_KERNEL::Exception(message.str().c_str());
178         }
179     }
180   if(_nodal_connec)
181     {
182       if(_nodal_connec->getNumberOfComponents()!=1)
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184       if(_nodal_connec->getInfoOnComponent(0)!="")
185         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
186     }
187   else
188     if(_mesh_dim!=-1)
189       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190   if(_nodal_connec_index)
191     {
192       if(_nodal_connec_index->getNumberOfComponents()!=1)
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194       if(_nodal_connec_index->getInfoOnComponent(0)!="")
195         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
196     }
197   else
198     if(_mesh_dim!=-1)
199       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
200 }
201
202 /*!
203  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204  * then \a this mesh is most probably is writable, exchangeable and available for all
205  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206  * method thoroughly checks the nodal connectivity.
207  *  \param [in] eps - a not used parameter.
208  *  \throw If the mesh dimension is not set.
209  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
210  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211  *  \throw If the connectivity data array has more than one component.
212  *  \throw If the connectivity data array has a named component.
213  *  \throw If the connectivity index data array has more than one component.
214  *  \throw If the connectivity index data array has a named component.
215  *  \throw If number of nodes defining an element does not correspond to the type of element.
216  *  \throw If the nodal connectivity includes an invalid node id.
217  */
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
219 {
220   checkCoherency();
221   if(_mesh_dim==-1)
222     return ;
223   int meshDim=getMeshDimension();
224   int nbOfNodes=getNumberOfNodes();
225   int nbOfCells=getNumberOfCells();
226   const int *ptr=_nodal_connec->getConstPointer();
227   const int *ptrI=_nodal_connec_index->getConstPointer();
228   for(int i=0;i<nbOfCells;i++)
229     {
230       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231       if((int)cm.getDimension()!=meshDim)
232         {
233           std::ostringstream oss;
234           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235           throw INTERP_KERNEL::Exception(oss.str().c_str());
236         }
237       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
238       if(!cm.isDynamic())
239         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
240           {
241             std::ostringstream oss;
242             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
243             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244             throw INTERP_KERNEL::Exception(oss.str().c_str());
245           }
246       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
247         {
248           int nodeId=*w;
249           if(nodeId>=0)
250             {
251               if(nodeId>=nbOfNodes)
252                 {
253                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
254                   throw INTERP_KERNEL::Exception(oss.str().c_str());
255                 }
256             }
257           else if(nodeId<-1)
258             {
259               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
260               throw INTERP_KERNEL::Exception(oss.str().c_str());
261             }
262           else
263             {
264               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
265                 {
266                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
267                   throw INTERP_KERNEL::Exception(oss.str().c_str());
268                 }
269             }
270         }
271     }
272 }
273
274
275 /*!
276  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
277  * then \a this mesh is most probably is writable, exchangeable and available for all
278  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
279  *  \param [in] eps - a not used parameter.
280  *  \throw If the mesh dimension is not set.
281  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
282  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
283  *  \throw If the connectivity data array has more than one component.
284  *  \throw If the connectivity data array has a named component.
285  *  \throw If the connectivity index data array has more than one component.
286  *  \throw If the connectivity index data array has a named component.
287  *  \throw If number of nodes defining an element does not correspond to the type of element.
288  *  \throw If the nodal connectivity includes an invalid node id.
289  */
290 void MEDCouplingUMesh::checkCoherency2(double eps) const
291 {
292   checkCoherency1(eps);
293 }
294
295 /*!
296  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
297  * elements contained in the mesh. For more info on the mesh dimension see
298  * \ref MEDCouplingUMeshPage.
299  *  \param [in] meshDim - a new mesh dimension.
300  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
301  */
302 void MEDCouplingUMesh::setMeshDimension(int meshDim)
303 {
304   if(meshDim<-1 || meshDim>3)
305     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
306   _mesh_dim=meshDim;
307   declareAsNew();
308 }
309
310 /*!
311  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
312  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
313  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
314  *
315  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
316  *
317  *  \if ENABLE_EXAMPLES
318  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
319  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
320  *  \endif
321  */
322 void MEDCouplingUMesh::allocateCells(int nbOfCells)
323 {
324   if(nbOfCells<0)
325     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
326   if(_nodal_connec_index)
327     {
328       _nodal_connec_index->decrRef();
329     }
330   if(_nodal_connec)
331     {
332       _nodal_connec->decrRef();
333     }
334   _nodal_connec_index=DataArrayInt::New();
335   _nodal_connec_index->reserve(nbOfCells+1);
336   _nodal_connec_index->pushBackSilent(0);
337   _nodal_connec=DataArrayInt::New();
338   _nodal_connec->reserve(2*nbOfCells);
339   _types.clear();
340   declareAsNew();
341 }
342
343 /*!
344  * Appends a cell to the connectivity array. For deeper understanding what is
345  * happening see \ref MEDCouplingUMeshNodalConnectivity.
346  *  \param [in] type - type of cell to add.
347  *  \param [in] size - number of nodes constituting this cell.
348  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
349  * 
350  *  \if ENABLE_EXAMPLES
351  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
352  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
353  *  \endif
354  */
355 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
356 {
357   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
358   if(_nodal_connec_index==0)
359     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
360   if((int)cm.getDimension()==_mesh_dim)
361     {
362       if(!cm.isDynamic())
363         if(size!=(int)cm.getNumberOfNodes())
364           {
365             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
366             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
367             throw INTERP_KERNEL::Exception(oss.str().c_str());
368           }
369       int idx=_nodal_connec_index->back();
370       int val=idx+size+1;
371       _nodal_connec_index->pushBackSilent(val);
372       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
373       _types.insert(type);
374     }
375   else
376     {
377       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
378       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
379       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
380       throw INTERP_KERNEL::Exception(oss.str().c_str());
381     }
382 }
383
384 /*!
385  * Compacts data arrays to release unused memory. This method is to be called after
386  * finishing cell insertion using \a this->insertNextCell().
387  * 
388  *  \if ENABLE_EXAMPLES
389  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
390  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
391  *  \endif
392  */
393 void MEDCouplingUMesh::finishInsertingCells()
394 {
395   _nodal_connec->pack();
396   _nodal_connec_index->pack();
397   _nodal_connec->declareAsNew();
398   _nodal_connec_index->declareAsNew();
399   updateTime();
400 }
401
402 /*!
403  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
404  * Useful for python users.
405  */
406 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
407 {
408   return new MEDCouplingUMeshCellIterator(this);
409 }
410
411 /*!
412  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
413  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
414  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
415  * Useful for python users.
416  */
417 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
418 {
419   if(!checkConsecutiveCellTypes())
420     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
421   return new MEDCouplingUMeshCellByTypeEntry(this);
422 }
423
424 /*!
425  * Returns a set of all cell types available in \a this mesh.
426  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
427  * \warning this method does not throw any exception even if \a this is not defined.
428  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
429  */
430 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
431 {
432   return _types;
433 }
434
435 /*!
436  * This method returns the sorted list of geometric types in \a this.
437  * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
438  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
439  *
440  * \throw if connectivity in \a this is not correctly defined.
441  *  
442  * \sa MEDCouplingMesh::getAllGeoTypes
443  */
444 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
445 {
446   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
447   checkConnectivityFullyDefined();
448   int nbOfCells(getNumberOfCells());
449   if(nbOfCells==0)
450     return ret;
451   if(getMeshLength()<1)
452     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
453   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
454   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
455   for(int i=1;i<nbOfCells;i++,ci++)
456     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
457       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
458   return ret;
459 }
460
461 /*!
462  * This method is a method that compares \a this and \a other.
463  * This method compares \b all attributes, even names and component names.
464  */
465 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
466 {
467   if(!other)
468     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
469   std::ostringstream oss; oss.precision(15);
470   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
471   if(!otherC)
472     {
473       reason="mesh given in input is not castable in MEDCouplingUMesh !";
474       return false;
475     }
476   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
477     return false;
478   if(_mesh_dim!=otherC->_mesh_dim)
479     {
480       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
481       reason=oss.str();
482       return false;
483     }
484   if(_types!=otherC->_types)
485     {
486       oss << "umesh geometric type mismatch :\nThis geometric types are :";
487       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
488         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
489       oss << "\nOther geometric types are :";
490       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
491         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
492       reason=oss.str();
493       return false;
494     }
495   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
496     if(_nodal_connec==0 || otherC->_nodal_connec==0)
497       {
498         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
499         return false;
500       }
501   if(_nodal_connec!=otherC->_nodal_connec)
502     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
503       {
504         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
505         return false;
506       }
507   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
508     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
509       {
510         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
511         return false;
512       }
513   if(_nodal_connec_index!=otherC->_nodal_connec_index)
514     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
515       {
516         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
517         return false;
518       }
519   return true;
520 }
521
522 /*!
523  * Checks if data arrays of this mesh (node coordinates, nodal
524  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
525  * not considered.
526  *  \param [in] other - the mesh to compare with.
527  *  \param [in] prec - precision value used to compare node coordinates.
528  *  \return bool - \a true if the two meshes are same.
529  */
530 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
531 {
532   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
533   if(!otherC)
534     return false;
535   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
536     return false;
537   if(_mesh_dim!=otherC->_mesh_dim)
538     return false;
539   if(_types!=otherC->_types)
540     return false;
541   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
542     if(_nodal_connec==0 || otherC->_nodal_connec==0)
543       return false;
544   if(_nodal_connec!=otherC->_nodal_connec)
545     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
546       return false;
547   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
548     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
549       return false;
550   if(_nodal_connec_index!=otherC->_nodal_connec_index)
551     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
552       return false;
553   return true;
554 }
555
556 /*!
557  * Checks if \a this and \a other meshes are geometrically equivalent with high
558  * probability, else an exception is thrown. The meshes are considered equivalent if
559  * (1) meshes contain the same number of nodes and the same number of elements of the
560  * same types (2) three cells of the two meshes (first, last and middle) are based
561  * on coincident nodes (with a specified precision).
562  *  \param [in] other - the mesh to compare with.
563  *  \param [in] prec - the precision used to compare nodes of the two meshes.
564  *  \throw If the two meshes do not match.
565  */
566 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
567 {
568   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
569   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
570   if(!otherC)
571     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
572 }
573
574 /*!
575  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
576  * cells each node belongs to.
577  * \warning For speed reasons, this method does not check if node ids in the nodal
578  *          connectivity correspond to the size of node coordinates array.
579  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
580  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
581  *        dividing cell ids in \a revNodal into groups each referring to one
582  *        node. Its every element (except the last one) is an index pointing to the
583  *         first id of a group of cells. For example cells sharing the node #1 are 
584  *        described by following range of indices: 
585  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
586  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
587  *        Number of cells sharing the *i*-th node is
588  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
589  * \throw If the coordinates array is not set.
590  * \throw If the nodal connectivity of cells is not defined.
591  * 
592  * \if ENABLE_EXAMPLES
593  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
594  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
595  * \endif
596  */
597 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
598 {
599   checkFullyDefined();
600   int nbOfNodes=getNumberOfNodes();
601   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
602   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
603   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
604   const int *conn=_nodal_connec->getConstPointer();
605   const int *connIndex=_nodal_connec_index->getConstPointer();
606   int nbOfCells=getNumberOfCells();
607   int nbOfEltsInRevNodal=0;
608   for(int eltId=0;eltId<nbOfCells;eltId++)
609     {
610       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
611       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
612       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
613         if(*iter>=0)//for polyhedrons
614           {
615             nbOfEltsInRevNodal++;
616             revNodalIndxPtr[(*iter)+1]++;
617           }
618     }
619   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
620   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
621   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
622   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
623   for(int eltId=0;eltId<nbOfCells;eltId++)
624     {
625       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
626       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
627       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
628         if(*iter>=0)//for polyhedrons
629           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
630     }
631 }
632
633 /// @cond INTERNAL
634
635 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
636 {
637   return id;
638 }
639
640 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
641 {
642   if(!compute)
643     return id+1;
644   else
645     {
646       if(cm.getOrientationStatus(nb,conn1,conn2))
647         return id+1;
648       else
649         return -(id+1);
650     }
651 }
652
653 class MinusOneSonsGenerator
654 {
655 public:
656   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
657   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
658   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
659   static const int DELTA=1;
660 private:
661   const INTERP_KERNEL::CellModel& _cm;
662 };
663
664 class MinusOneSonsGeneratorBiQuadratic
665 {
666 public:
667   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
668   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
669   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
670   static const int DELTA=1;
671 private:
672   const INTERP_KERNEL::CellModel& _cm;
673 };
674
675 class MinusTwoSonsGenerator
676 {
677 public:
678   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
679   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
680   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
681   static const int DELTA=2;
682 private:
683   const INTERP_KERNEL::CellModel& _cm;
684 };
685
686 /// @endcond
687
688 /*!
689  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
690  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
691  * describing correspondence between cells of \a this and the result meshes are
692  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
693  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
694  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
695  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
696  * \warning For speed reasons, this method does not check if node ids in the nodal
697  *          connectivity correspond to the size of node coordinates array.
698  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
699  *          to write this mesh to the MED file, its cells must be sorted using
700  *          sortCellsInMEDFileFrmt().
701  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
702  *         each cell of \a this mesh.
703  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
704  *        dividing cell ids in \a desc into groups each referring to one
705  *        cell of \a this mesh. Its every element (except the last one) is an index
706  *        pointing to the first id of a group of cells. For example cells of the
707  *        result mesh bounding the cell #1 of \a this mesh are described by following
708  *        range of indices:
709  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
710  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
711  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
712  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
713  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
714  *         by each cell of the result mesh.
715  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
716  *        in the result mesh,
717  *        dividing cell ids in \a revDesc into groups each referring to one
718  *        cell of the result mesh the same way as \a descIndx divides \a desc.
719  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
720  *        delete this mesh using decrRef() as it is no more needed.
721  *  \throw If the coordinates array is not set.
722  *  \throw If the nodal connectivity of cells is node defined.
723  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
724  *         revDescIndx == NULL.
725  * 
726  *  \if ENABLE_EXAMPLES
727  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
728  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
729  *  \endif
730  * \sa buildDescendingConnectivity2()
731  */
732 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
733 {
734   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
735 }
736
737 /*!
738  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
739  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
740  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
741  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
742  * \sa MEDCouplingUMesh::buildDescendingConnectivity
743  */
744 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
745 {
746   checkFullyDefined();
747   if(getMeshDimension()!=3)
748     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
749   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
750 }
751
752 /*!
753  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
754  * this->getMeshDimension(), that bound cells of \a this mesh. In
755  * addition arrays describing correspondence between cells of \a this and the result
756  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
757  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
758  *  mesh. This method differs from buildDescendingConnectivity() in that apart
759  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
760  * result meshes. So a positive id means that order of nodes in corresponding cells
761  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
762  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
763  * i.e. cell ids are one-based.
764  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
765  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
766  * \warning For speed reasons, this method does not check if node ids in the nodal
767  *          connectivity correspond to the size of node coordinates array.
768  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
769  *          to write this mesh to the MED file, its cells must be sorted using
770  *          sortCellsInMEDFileFrmt().
771  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
772  *         each cell of \a this mesh.
773  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
774  *        dividing cell ids in \a desc into groups each referring to one
775  *        cell of \a this mesh. Its every element (except the last one) is an index
776  *        pointing to the first id of a group of cells. For example cells of the
777  *        result mesh bounding the cell #1 of \a this mesh are described by following
778  *        range of indices:
779  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
780  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
781  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
782  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
783  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
784  *         by each cell of the result mesh.
785  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
786  *        in the result mesh,
787  *        dividing cell ids in \a revDesc into groups each referring to one
788  *        cell of the result mesh the same way as \a descIndx divides \a desc.
789  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
790  *        shares the node coordinates array with \a this mesh. The caller is to
791  *        delete this mesh using decrRef() as it is no more needed.
792  *  \throw If the coordinates array is not set.
793  *  \throw If the nodal connectivity of cells is node defined.
794  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
795  *         revDescIndx == NULL.
796  * 
797  *  \if ENABLE_EXAMPLES
798  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
799  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
800  *  \endif
801  * \sa buildDescendingConnectivity()
802  */
803 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
804 {
805   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
806 }
807
808 /*!
809  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
810  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
811  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
812  * The 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    * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4190    */
4191   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map<INTERP_KERNEL::Node *,int>& m)
4192   {
4193     INTERP_KERNEL::Edge *ret=0;
4194     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]));
4195     m[n0]=bg[0]; m[n1]=bg[1];
4196     switch(typ)
4197     {
4198       case INTERP_KERNEL::NORM_SEG2:
4199         {
4200           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4201           break;
4202         }
4203       case INTERP_KERNEL::NORM_SEG3:
4204         {
4205           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4206           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4207           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4208           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4209           bool colinearity(inters.areColinears());
4210           delete e1; delete e2;
4211           if(colinearity)
4212             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4213           else
4214             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4215           break;
4216         }
4217       default:
4218         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4219     }
4220     return ret;
4221   }
4222
4223   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4224   {
4225     INTERP_KERNEL::Edge *ret=0;
4226     switch(typ)
4227     {
4228       case INTERP_KERNEL::NORM_SEG2:
4229         {
4230           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4231           break;
4232         }
4233       case INTERP_KERNEL::NORM_SEG3:
4234         {
4235           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4236           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4237           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4238           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4239           bool colinearity=inters.areColinears();
4240           delete e1; delete e2;
4241           if(colinearity)
4242             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4243           else
4244             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4245           mapp2[bg[2]].second=false;
4246           break;
4247         }
4248       default:
4249         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4250     }
4251     return ret;
4252   }
4253
4254   /*!
4255    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4256    * the global mesh 'mDesc'.
4257    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4258    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4259    */
4260   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4261                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4262   {
4263     mapp.clear();
4264     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.
4265     const double *coo=mDesc->getCoords()->getConstPointer();
4266     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4267     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4268     std::set<int> s;
4269     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4270       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4271     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4272       {
4273         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4274         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4275       }
4276     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4277     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4278       {
4279         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4280         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4281       }
4282     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4283       {
4284         if((*it2).second.second)
4285           mapp[(*it2).second.first]=(*it2).first;
4286         ((*it2).second.first)->decrRef();
4287       }
4288     return ret;
4289   }
4290
4291   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4292   {
4293     if(nodeId>=offset2)
4294       {
4295         int locId=nodeId-offset2;
4296         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4297       }
4298     if(nodeId>=offset1)
4299       {
4300         int locId=nodeId-offset1;
4301         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4302       }
4303     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4304   }
4305
4306   /**
4307    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4308    */
4309   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4310                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4311                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4312   {
4313     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4314       {
4315         int eltId1=abs(*desc1)-1;
4316         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4317           {
4318             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4319             if(it==mappRev.end())
4320               {
4321                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4322                 mapp[node]=*it1;
4323                 mappRev[*it1]=node;
4324               }
4325           }
4326       }
4327   }
4328 }
4329
4330 /// @endcond
4331
4332 template<int SPACEDIM>
4333 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4334                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4335 {
4336   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4337   int *eltsIndexPtr(eltsIndex->getPointer());
4338   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4339   const double *bbox(bboxArr->begin());
4340   int nbOfCells=getNumberOfCells();
4341   const int *conn=_nodal_connec->getConstPointer();
4342   const int *connI=_nodal_connec_index->getConstPointer();
4343   double bb[2*SPACEDIM];
4344   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4345   for(int i=0;i<nbOfPoints;i++)
4346     {
4347       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4348       for(int j=0;j<SPACEDIM;j++)
4349         {
4350           bb[2*j]=pos[SPACEDIM*i+j];
4351           bb[2*j+1]=pos[SPACEDIM*i+j];
4352         }
4353       std::vector<int> candidates;
4354       myTree.getIntersectingElems(bb,candidates);
4355       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4356         {
4357           int sz(connI[(*iter)+1]-connI[*iter]-1);
4358           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4359           bool status(false);
4360           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4361             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4362           else
4363             {
4364               if(SPACEDIM!=2)
4365                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4366               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4367               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4368               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4369               INTERP_KERNEL::QuadraticPolygon *pol(0);
4370               for(int j=0;j<sz;j++)
4371                 {
4372                   int nodeId(conn[connI[*iter]+1+j]);
4373                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4374                 }
4375               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4376                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4377               else
4378                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4379               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4380               double a(0.),b(0.),c(0.);
4381               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4382               status=pol->isInOrOut2(n);
4383               delete pol; n->decrRef();
4384             }
4385           if(status)
4386             {
4387               eltsIndexPtr[i+1]++;
4388               elts->pushBackSilent(*iter);
4389             }
4390         }
4391     }
4392 }
4393 /*!
4394  * Finds cells in contact with several balls (i.e. points with precision).
4395  * This method is an extension of getCellContainingPoint() and
4396  * getCellsContainingPoint() for the case of multiple points.
4397  * 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.
4398  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4399  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4400  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4401  *         this->getSpaceDimension() * \a nbOfPoints 
4402  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4403  *  \param [in] eps - radius of balls (i.e. the precision).
4404  *  \param [out] elts - vector returning ids of found cells.
4405  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4406  *         dividing cell ids in \a elts into groups each referring to one
4407  *         point. Its every element (except the last one) is an index pointing to the
4408  *         first id of a group of cells. For example cells in contact with the *i*-th
4409  *         point are described by following range of indices:
4410  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4411  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4412  *         Number of cells in contact with the *i*-th point is
4413  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4414  *  \throw If the coordinates array is not set.
4415  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4416  *
4417  *  \if ENABLE_EXAMPLES
4418  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4419  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4420  *  \endif
4421  */
4422 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4423                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4424 {
4425   int spaceDim=getSpaceDimension();
4426   int mDim=getMeshDimension();
4427   if(spaceDim==3)
4428     {
4429       if(mDim==3)
4430         {
4431           const double *coords=_coords->getConstPointer();
4432           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4433         }
4434       /*else if(mDim==2)
4435         {
4436
4437         }*/
4438       else
4439         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4440     }
4441   else if(spaceDim==2)
4442     {
4443       if(mDim==2)
4444         {
4445           const double *coords=_coords->getConstPointer();
4446           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4447         }
4448       else
4449         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4450     }
4451   else if(spaceDim==1)
4452     {
4453       if(mDim==1)
4454         {
4455           const double *coords=_coords->getConstPointer();
4456           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4457         }
4458       else
4459         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4460     }
4461   else
4462     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4463 }
4464
4465 /*!
4466  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4467  * least two its edges intersect each other anywhere except their extremities. An
4468  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4469  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4470  *         cleared before filling in.
4471  *  \param [in] eps - precision.
4472  *  \throw If \a this->getMeshDimension() != 2.
4473  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4474  */
4475 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4476 {
4477   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4478   if(getMeshDimension()!=2)
4479     throw INTERP_KERNEL::Exception(msg);
4480   int spaceDim=getSpaceDimension();
4481   if(spaceDim!=2 && spaceDim!=3)
4482     throw INTERP_KERNEL::Exception(msg);
4483   const int *conn=_nodal_connec->getConstPointer();
4484   const int *connI=_nodal_connec_index->getConstPointer();
4485   int nbOfCells=getNumberOfCells();
4486   std::vector<double> cell2DinS2;
4487   for(int i=0;i<nbOfCells;i++)
4488     {
4489       int offset=connI[i];
4490       int nbOfNodesForCell=connI[i+1]-offset-1;
4491       if(nbOfNodesForCell<=3)
4492         continue;
4493       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4494       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4495       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4496         cells.push_back(i);
4497       cell2DinS2.clear();
4498     }
4499 }
4500
4501 /*!
4502  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4503  *
4504  * 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.
4505  * 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.
4506  * 
4507  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4508  * This convex envelop is computed using Jarvis march algorithm.
4509  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4510  * 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)
4511  * 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.
4512  *
4513  * \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.
4514  * \sa MEDCouplingUMesh::colinearize2D
4515  */
4516 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4517 {
4518   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4519     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4520   checkFullyDefined();
4521   const double *coords=getCoords()->getConstPointer();
4522   int nbOfCells=getNumberOfCells();
4523   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4524   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4525   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4526   int *workIndexOut=nodalConnecIndexOut->getPointer();
4527   *workIndexOut=0;
4528   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4529   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4530   std::set<INTERP_KERNEL::NormalizedCellType> types;
4531   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4532   isChanged->alloc(0,1);
4533   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4534     {
4535       int pos=nodalConnecOut->getNumberOfTuples();
4536       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4537         isChanged->pushBackSilent(i);
4538       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4539       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4540     }
4541   if(isChanged->empty())
4542     return 0;
4543   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4544   _types=types;
4545   return isChanged.retn();
4546 }
4547
4548 /*!
4549  * This method is \b NOT const because it can modify \a this.
4550  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4551  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4552  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4553  * \b 1 for translation and rotation around point of 'mesh1D'.
4554  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4555  */
4556 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4557 {
4558   checkFullyDefined();
4559   mesh1D->checkFullyDefined();
4560   if(!mesh1D->isContiguous1D())
4561     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4562   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4563     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4564   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4565     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4566   if(mesh1D->getMeshDimension()!=1)
4567     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4568   bool isQuad=false;
4569   if(isPresenceOfQuadratic())
4570     {
4571       if(mesh1D->isFullyQuadratic())
4572         isQuad=true;
4573       else
4574         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4575     }
4576   zipCoords();
4577   int oldNbOfNodes=getNumberOfNodes();
4578   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4579   switch(policy)
4580   {
4581     case 0:
4582       {
4583         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4584         break;
4585       }
4586     case 1:
4587       {
4588         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4589         break;
4590       }
4591     default:
4592       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4593   }
4594   setCoords(newCoords);
4595   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4596   updateTime();
4597   return ret.retn();
4598 }
4599
4600 /*!
4601  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4602  * If it is not the case an exception will be thrown.
4603  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4604  * intersection of plane defined by ('origin','vec').
4605  * This method has one in/out parameter : 'cut3DCurve'.
4606  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4607  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4608  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4609  * This method will throw an exception if \a this contains a non linear segment.
4610  */
4611 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4612 {
4613   checkFullyDefined();
4614   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4615     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4616   int ncells=getNumberOfCells();
4617   int nnodes=getNumberOfNodes();
4618   double vec2[3],vec3[3],vec4[3];
4619   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4620   if(normm<1e-6)
4621     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4622   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4623   const int *conn=_nodal_connec->getConstPointer();
4624   const int *connI=_nodal_connec_index->getConstPointer();
4625   const double *coo=_coords->getConstPointer();
4626   std::vector<double> addCoo;
4627   for(int i=0;i<ncells;i++)
4628     {
4629       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4630         {
4631           if(cut3DCurve[i]==-2)
4632             {
4633               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4634               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];
4635               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4636               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4637               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4638                 {
4639                   const double *st2=coo+3*st;
4640                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4641                   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]));
4642                   if(pos>eps && pos<1-eps)
4643                     {
4644                       int nNode=((int)addCoo.size())/3;
4645                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4646                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4647                       cut3DCurve[i]=nnodes+nNode;
4648                     }
4649                 }
4650             }
4651         }
4652       else
4653         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4654     }
4655   if(!addCoo.empty())
4656     {
4657       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4658       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4659       coo2->alloc(newNbOfNodes,3);
4660       double *tmp=coo2->getPointer();
4661       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4662       std::copy(addCoo.begin(),addCoo.end(),tmp);
4663       DataArrayDouble::SetArrayIn(coo2,_coords);
4664     }
4665 }
4666
4667 /*!
4668  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4669  * \param mesh1D is the input 1D mesh used for translation computation.
4670  * \return newCoords new coords filled by this method. 
4671  */
4672 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4673 {
4674   int oldNbOfNodes=getNumberOfNodes();
4675   int nbOf1DCells=mesh1D->getNumberOfCells();
4676   int spaceDim=getSpaceDimension();
4677   DataArrayDouble *ret=DataArrayDouble::New();
4678   std::vector<bool> isQuads;
4679   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4680   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4681   double *retPtr=ret->getPointer();
4682   const double *coords=getCoords()->getConstPointer();
4683   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4684   std::vector<int> v;
4685   std::vector<double> c;
4686   double vec[3];
4687   v.reserve(3);
4688   c.reserve(6);
4689   for(int i=0;i<nbOf1DCells;i++)
4690     {
4691       v.resize(0);
4692       mesh1D->getNodeIdsOfCell(i,v);
4693       c.resize(0);
4694       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4695       mesh1D->getCoordinatesOfNode(v[0],c);
4696       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4697       for(int j=0;j<oldNbOfNodes;j++)
4698         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4699       if(isQuad)
4700         {
4701           c.resize(0);
4702           mesh1D->getCoordinatesOfNode(v[1],c);
4703           mesh1D->getCoordinatesOfNode(v[0],c);
4704           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4705           for(int j=0;j<oldNbOfNodes;j++)
4706             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4707         }
4708     }
4709   ret->copyStringInfoFrom(*getCoords());
4710   return ret;
4711 }
4712
4713 /*!
4714  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4715  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4716  * \return newCoords new coords filled by this method. 
4717  */
4718 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4719 {
4720   if(mesh1D->getSpaceDimension()==2)
4721     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4722   if(mesh1D->getSpaceDimension()==3)
4723     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4724   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4725 }
4726
4727 /*!
4728  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4729  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4730  * \return newCoords new coords filled by this method. 
4731  */
4732 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4733 {
4734   if(isQuad)
4735     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4736   int oldNbOfNodes=getNumberOfNodes();
4737   int nbOf1DCells=mesh1D->getNumberOfCells();
4738   if(nbOf1DCells<2)
4739     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4740   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4741   int nbOfLevsInVec=nbOf1DCells+1;
4742   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4743   double *retPtr=ret->getPointer();
4744   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4745   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4746   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4747   tmp->setCoords(tmp2);
4748   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4749   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4750   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4751   for(int i=1;i<nbOfLevsInVec;i++)
4752     {
4753       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4754       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4755       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4756       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4757       tmp->translate(vec);
4758       double tmp3[2],radius,alpha,alpha0;
4759       const double *p0=i+1<nbOfLevsInVec?begin:third;
4760       const double *p1=i+1<nbOfLevsInVec?end:begin;
4761       const double *p2=i+1<nbOfLevsInVec?third:end;
4762       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4763       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]);
4764       double angle=acos(cosangle/(radius*radius));
4765       tmp->rotate(end,0,angle);
4766       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4767     }
4768   return ret.retn();
4769 }
4770
4771 /*!
4772  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4773  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4774  * \return newCoords new coords filled by this method. 
4775  */
4776 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4777 {
4778   if(isQuad)
4779     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4780   int oldNbOfNodes=getNumberOfNodes();
4781   int nbOf1DCells=mesh1D->getNumberOfCells();
4782   if(nbOf1DCells<2)
4783     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4784   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4785   int nbOfLevsInVec=nbOf1DCells+1;
4786   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4787   double *retPtr=ret->getPointer();
4788   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4789   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4790   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4791   tmp->setCoords(tmp2);
4792   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4793   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4794   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4795   for(int i=1;i<nbOfLevsInVec;i++)
4796     {
4797       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4798       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4799       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4800       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4801       tmp->translate(vec);
4802       double tmp3[2],radius,alpha,alpha0;
4803       const double *p0=i+1<nbOfLevsInVec?begin:third;
4804       const double *p1=i+1<nbOfLevsInVec?end:begin;
4805       const double *p2=i+1<nbOfLevsInVec?third:end;
4806       double vecPlane[3]={
4807         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4808         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4809         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4810       };
4811       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4812       if(norm>1.e-7)
4813         {
4814           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4815           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4816           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4817           double s2=norm2;
4818           double c2=cos(asin(s2));
4819           double m[3][3]={
4820             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4821             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4822             {-vec2[1]*s2, vec2[0]*s2, c2}
4823           };
4824           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]};
4825           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]};
4826           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]};
4827           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4828           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]);
4829           double angle=acos(cosangle/(radius*radius));
4830           tmp->rotate(end,vecPlane,angle);
4831         }
4832       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4833     }
4834   return ret.retn();
4835 }
4836
4837 /*!
4838  * This method is private because not easy to use for end user. This method is const contrary to
4839  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4840  * the coords sorted slice by slice.
4841  * \param isQuad specifies presence of quadratic cells.
4842  */
4843 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4844 {
4845   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4846   int nbOf2DCells=getNumberOfCells();
4847   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4848   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4849   const int *conn=_nodal_connec->getConstPointer();
4850   const int *connI=_nodal_connec_index->getConstPointer();
4851   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4852   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4853   newConnI->alloc(nbOf3DCells+1,1);
4854   int *newConnIPtr=newConnI->getPointer();
4855   *newConnIPtr++=0;
4856   std::vector<int> newc;
4857   for(int j=0;j<nbOf2DCells;j++)
4858     {
4859       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4860       *newConnIPtr++=(int)newc.size();
4861     }
4862   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4863   int *newConnPtr=newConn->getPointer();
4864   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4865   newConnIPtr=newConnI->getPointer();
4866   for(int iz=0;iz<nbOf1DCells;iz++)
4867     {
4868       if(iz!=0)
4869         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4870       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4871         {
4872           int icell=(int)(iter-newc.begin());
4873           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4874             {
4875               if(*iter!=-1)
4876                 *newConnPtr=(*iter)+iz*deltaPerLev;
4877               else
4878                 *newConnPtr=-1;
4879             }
4880           else
4881             *newConnPtr=(*iter);
4882         }
4883     }
4884   ret->setConnectivity(newConn,newConnI,true);
4885   ret->setCoords(getCoords());
4886   return ret;
4887 }
4888
4889 /*!
4890  * Checks if \a this mesh is constituted by only quadratic cells.
4891  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4892  *  \throw If the coordinates array is not set.
4893  *  \throw If the nodal connectivity of cells is not defined.
4894  */
4895 bool MEDCouplingUMesh::isFullyQuadratic() const
4896 {
4897   checkFullyDefined();
4898   bool ret=true;
4899   int nbOfCells=getNumberOfCells();
4900   for(int i=0;i<nbOfCells && ret;i++)
4901     {
4902       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4903       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4904       ret=cm.isQuadratic();
4905     }
4906   return ret;
4907 }
4908
4909 /*!
4910  * Checks if \a this mesh includes any quadratic cell.
4911  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4912  *  \throw If the coordinates array is not set.
4913  *  \throw If the nodal connectivity of cells is not defined.
4914  */
4915 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4916 {
4917   checkFullyDefined();
4918   bool ret=false;
4919   int nbOfCells=getNumberOfCells();
4920   for(int i=0;i<nbOfCells && !ret;i++)
4921     {
4922       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4923       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4924       ret=cm.isQuadratic();
4925     }
4926   return ret;
4927 }
4928
4929 /*!
4930  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4931  * this mesh, it remains unchanged.
4932  *  \throw If the coordinates array is not set.
4933  *  \throw If the nodal connectivity of cells is not defined.
4934  */
4935 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4936 {
4937   checkFullyDefined();
4938   int nbOfCells=getNumberOfCells();
4939   int delta=0;
4940   const int *iciptr=_nodal_connec_index->getConstPointer();
4941   for(int i=0;i<nbOfCells;i++)
4942     {
4943       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4944       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4945       if(cm.isQuadratic())
4946         {
4947           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4948           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4949           if(!cml.isDynamic())
4950             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4951           else
4952             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4953         }
4954     }
4955   if(delta==0)
4956     return ;
4957   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4958   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4959   const int *icptr=_nodal_connec->getConstPointer();
4960   newConn->alloc(getMeshLength()-delta,1);
4961   newConnI->alloc(nbOfCells+1,1);
4962   int *ocptr=newConn->getPointer();
4963   int *ociptr=newConnI->getPointer();
4964   *ociptr=0;
4965   _types.clear();
4966   for(int i=0;i<nbOfCells;i++,ociptr++)
4967     {
4968       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4969       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4970       if(!cm.isQuadratic())
4971         {
4972           _types.insert(type);
4973           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4974           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4975         }
4976       else
4977         {
4978           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4979           _types.insert(typel);
4980           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4981           int newNbOfNodes=cml.getNumberOfNodes();
4982           if(cml.isDynamic())
4983             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4984           *ocptr++=(int)typel;
4985           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4986           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4987         }
4988     }
4989   setConnectivity(newConn,newConnI,false);
4990 }
4991
4992 /*!
4993  * This method converts all linear cell in \a this to quadratic one.
4994  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4995  * 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)
4996  * 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.
4997  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4998  * end of the existing coordinates.
4999  * 
5000  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5001  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5002  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5003  * 
5004  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5005  *
5006  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5007  */
5008 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5009 {
5010   DataArrayInt *conn=0,*connI=0;
5011   DataArrayDouble *coords=0;
5012   std::set<INTERP_KERNEL::NormalizedCellType> types;
5013   checkFullyDefined();
5014   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5015   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5016   int meshDim=getMeshDimension();
5017   switch(conversionType)
5018   {
5019     case 0:
5020       switch(meshDim)
5021       {
5022         case 1:
5023           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5024           connSafe=conn; connISafe=connI; coordsSafe=coords;
5025           break;
5026         case 2:
5027           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5028           connSafe=conn; connISafe=connI; coordsSafe=coords;
5029           break;
5030         case 3:
5031           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5032           connSafe=conn; connISafe=connI; coordsSafe=coords;
5033           break;
5034         default:
5035           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5036       }
5037       break;
5038         case 1:
5039           {
5040             switch(meshDim)
5041             {
5042               case 1:
5043                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5044                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5045                 break;
5046               case 2:
5047                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5048                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5049                 break;
5050               case 3:
5051                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5052                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5053                 break;
5054               default:
5055                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5056             }
5057             break;
5058           }
5059         default:
5060           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5061   }
5062   setConnectivity(connSafe,connISafe,false);
5063   _types=types;
5064   setCoords(coordsSafe);
5065   return ret.retn();
5066 }
5067
5068 /*!
5069  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5070  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5071  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5072  */
5073 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5074 {
5075   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5076   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5077   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5078   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5079   int nbOfCells=getNumberOfCells();
5080   int nbOfNodes=getNumberOfNodes();
5081   const int *cPtr=_nodal_connec->getConstPointer();
5082   const int *icPtr=_nodal_connec_index->getConstPointer();
5083   int lastVal=0,offset=nbOfNodes;
5084   for(int i=0;i<nbOfCells;i++,icPtr++)
5085     {
5086       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5087       if(type==INTERP_KERNEL::NORM_SEG2)
5088         {
5089           types.insert(INTERP_KERNEL::NORM_SEG3);
5090           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5091           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5092           newConn->pushBackSilent(offset++);
5093           lastVal+=4;
5094           newConnI->pushBackSilent(lastVal);
5095           ret->pushBackSilent(i);
5096         }
5097       else
5098         {
5099           types.insert(type);
5100           lastVal+=(icPtr[1]-icPtr[0]);
5101           newConnI->pushBackSilent(lastVal);
5102           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5103         }
5104     }
5105   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5106   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5107   return ret.retn();
5108 }
5109
5110 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
5111 {
5112   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5113   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5114   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5115   //
5116   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5117   DataArrayInt *conn1D=0,*conn1DI=0;
5118   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5119   DataArrayDouble *coordsTmp=0;
5120   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5121   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5122   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5123   const int *c1DPtr=conn1D->begin();
5124   const int *c1DIPtr=conn1DI->begin();
5125   int nbOfCells=getNumberOfCells();
5126   const int *cPtr=_nodal_connec->getConstPointer();
5127   const int *icPtr=_nodal_connec_index->getConstPointer();
5128   int lastVal=0;
5129   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5130     {
5131       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5132       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5133       if(!cm.isQuadratic())
5134         {
5135           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5136           types.insert(typ2); newConn->pushBackSilent(typ2);
5137           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5138           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5139             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5140           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5141           newConnI->pushBackSilent(lastVal);
5142           ret->pushBackSilent(i);
5143         }
5144       else
5145         {
5146           types.insert(typ);
5147           lastVal+=(icPtr[1]-icPtr[0]);
5148           newConnI->pushBackSilent(lastVal);
5149           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5150         }
5151     }
5152   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5153   return ret.retn();
5154 }
5155
5156 /*!
5157  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5158  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5159  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5160  */
5161 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5162 {
5163   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5164   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5165   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5166 }
5167
5168 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5169 {
5170   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5171   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5172   //
5173   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5174   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5175   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5176   //
5177   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5178   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5179   DataArrayInt *conn1D=0,*conn1DI=0;
5180   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5181   DataArrayDouble *coordsTmp=0;
5182   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5183   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5184   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5185   const int *c1DPtr=conn1D->begin();
5186   const int *c1DIPtr=conn1DI->begin();
5187   int nbOfCells=getNumberOfCells();
5188   const int *cPtr=_nodal_connec->getConstPointer();
5189   const int *icPtr=_nodal_connec_index->getConstPointer();
5190   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5191   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5192     {
5193       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5194       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5195       if(!cm.isQuadratic())
5196         {
5197           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5198           types.insert(typ2); newConn->pushBackSilent(typ2);
5199           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5200           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5201             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5202           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5203           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5204           newConnI->pushBackSilent(lastVal);
5205           ret->pushBackSilent(i);
5206         }
5207       else
5208         {
5209           types.insert(typ);
5210           lastVal+=(icPtr[1]-icPtr[0]);
5211           newConnI->pushBackSilent(lastVal);
5212           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5213         }
5214     }
5215   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5216   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5217   return ret.retn();
5218 }
5219
5220 /*!
5221  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5222  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5223  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5224  */
5225 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5226 {
5227   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5228   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5229   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5230 }
5231
5232 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5233 {
5234   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5235   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5236   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5237   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5238   //
5239   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5240   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5241   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5242   //
5243   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5244   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5245   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5246   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5247   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5248   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5249   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5250   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5251   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5252   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5253   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5254   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5255   int nbOfCells=getNumberOfCells();
5256   const int *cPtr=_nodal_connec->getConstPointer();
5257   const int *icPtr=_nodal_connec_index->getConstPointer();
5258   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5259   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5260     {
5261       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5262       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5263       if(!cm.isQuadratic())
5264         {
5265           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5266           if(typ2==INTERP_KERNEL::NORM_ERROR)
5267             {
5268               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5269               throw INTERP_KERNEL::Exception(oss.str().c_str());
5270             }
5271           types.insert(typ2); newConn->pushBackSilent(typ2);
5272           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5273           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5274             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5275           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5276             {
5277               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5278               int tmpPos=newConn->getNumberOfTuples();
5279               newConn->pushBackSilent(nodeId2);
5280               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5281             }
5282           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5283           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5284           newConnI->pushBackSilent(lastVal);
5285           ret->pushBackSilent(i);
5286         }
5287       else
5288         {
5289           types.insert(typ);
5290           lastVal+=(icPtr[1]-icPtr[0]);
5291           newConnI->pushBackSilent(lastVal);
5292           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5293         }
5294     }
5295   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5296   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5297   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5298   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5299   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5300   int *c=newConn->getPointer();
5301   const int *cI(newConnI->begin());
5302   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5303     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5304   offset=coordsTmp2Safe->getNumberOfTuples();
5305   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5306     c[cI[(*elt)+1]-1]+=offset;
5307   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5308   return ret.retn();
5309 }
5310
5311 /*!
5312  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5313  * so that the number of cells remains the same. Quadratic faces are converted to
5314  * polygons. This method works only for 2D meshes in
5315  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5316  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5317  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5318  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5319  *         a polylinized edge constituting the input polygon.
5320  *  \throw If the coordinates array is not set.
5321  *  \throw If the nodal connectivity of cells is not defined.
5322  *  \throw If \a this->getMeshDimension() != 2.
5323  *  \throw If \a this->getSpaceDimension() != 2.
5324  */
5325 void MEDCouplingUMesh::tessellate2D(double eps)
5326 {
5327   checkFullyDefined();
5328   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5329     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5330   double epsa=fabs(eps);
5331   if(epsa<std::numeric_limits<double>::min())
5332     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 !");
5333   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5334   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5337   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5338   revDesc1=0; revDescIndx1=0;
5339   mDesc->tessellate2DCurve(eps);
5340   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5341   setCoords(mDesc->getCoords());
5342 }
5343
5344 /*!
5345  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5346  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5347  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5348  *         a sub-divided edge.
5349  *  \throw If the coordinates array is not set.
5350  *  \throw If the nodal connectivity of cells is not defined.
5351  *  \throw If \a this->getMeshDimension() != 1.
5352  *  \throw If \a this->getSpaceDimension() != 2.
5353  */
5354 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5355 {
5356   checkFullyDefined();
5357   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5358     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5359   double epsa=fabs(eps);
5360   if(epsa<std::numeric_limits<double>::min())
5361     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 !");
5362   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5363   int nbCells=getNumberOfCells();
5364   int nbNodes=getNumberOfNodes();
5365   const int *conn=_nodal_connec->getConstPointer();
5366   const int *connI=_nodal_connec_index->getConstPointer();
5367   const double *coords=_coords->getConstPointer();
5368   std::vector<double> addCoo;
5369   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5370   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5371   newConnI->alloc(nbCells+1,1);
5372   int *newConnIPtr=newConnI->getPointer();
5373   *newConnIPtr=0;
5374   int tmp1[3];
5375   INTERP_KERNEL::Node *tmp2[3];
5376   std::set<INTERP_KERNEL::NormalizedCellType> types;
5377   for(int i=0;i<nbCells;i++,newConnIPtr++)
5378     {
5379       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5380       if(cm.isQuadratic())
5381         {//assert(connI[i+1]-connI[i]-1==3)
5382           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5383           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5384           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5385           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5386           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5387           if(eac)
5388             {
5389               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5390               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5391               delete eac;
5392               newConnIPtr[1]=(int)newConn.size();
5393             }
5394           else
5395             {
5396               types.insert(INTERP_KERNEL::NORM_SEG2);
5397               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5398               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5399               newConnIPtr[1]=newConnIPtr[0]+3;
5400             }
5401         }
5402       else
5403         {
5404           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5405           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5406           newConnIPtr[1]=newConnIPtr[0]+3;
5407         }
5408     }
5409   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5410     return ;
5411   _types=types;
5412   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5413   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5414   newConnArr->alloc((int)newConn.size(),1);
5415   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5416   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5417   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5418   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5419   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5420   std::copy(addCoo.begin(),addCoo.end(),work);
5421   DataArrayDouble::SetArrayIn(newCoords,_coords);
5422   updateTime();
5423 }
5424
5425 /*!
5426  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5427  * In addition, returns an array mapping new cells to old ones. <br>
5428  * This method typically increases the number of cells in \a this mesh
5429  * but the number of nodes remains \b unchanged.
5430  * That's why the 3D splitting policies
5431  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5432  *  \param [in] policy - specifies a pattern used for splitting.
5433  * The semantic of \a policy is:
5434  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5435  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5436  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5437  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5438  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5439  *          an id of old cell producing it. The caller is to delete this array using
5440  *         decrRef() as it is no more needed. 
5441  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5442  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5443  *          and \a this->getMeshDimension() != 3. 
5444  *  \throw If \a policy is not one of the four discussed above.
5445  *  \throw If the nodal connectivity of cells is not defined.
5446  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5447  */
5448 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5449 {
5450   switch(policy)
5451   {
5452     case 0:
5453       return simplexizePol0();
5454     case 1:
5455       return simplexizePol1();
5456     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5457         return simplexizePlanarFace5();
5458     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5459         return simplexizePlanarFace6();
5460     default:
5461       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)");
5462   }
5463 }
5464
5465 /*!
5466  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5467  * - 1D: INTERP_KERNEL::NORM_SEG2
5468  * - 2D: INTERP_KERNEL::NORM_TRI3
5469  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5470  *
5471  * This method is useful for users that need to use P1 field services as
5472  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5473  * All these methods need mesh support containing only simplex cells.
5474  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5475  *  \throw If the coordinates array is not set.
5476  *  \throw If the nodal connectivity of cells is not defined.
5477  *  \throw If \a this->getMeshDimension() < 1.
5478  */
5479 bool MEDCouplingUMesh::areOnlySimplexCells() const
5480 {
5481   checkFullyDefined();
5482   int mdim=getMeshDimension();
5483   if(mdim<1 || mdim>3)
5484     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5485   int nbCells=getNumberOfCells();
5486   const int *conn=_nodal_connec->getConstPointer();
5487   const int *connI=_nodal_connec_index->getConstPointer();
5488   for(int i=0;i<nbCells;i++)
5489     {
5490       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5491       if(!cm.isSimplex())
5492         return false;
5493     }
5494   return true;
5495 }
5496
5497 /*!
5498  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5499  */
5500 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5501 {
5502   checkConnectivityFullyDefined();
5503   if(getMeshDimension()!=2)
5504     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5505   int nbOfCells=getNumberOfCells();
5506   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5507   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5508   ret->alloc(nbOfCells+nbOfCutCells,1);
5509   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5510   int *retPt=ret->getPointer();
5511   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5512   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5513   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5514   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5515   int *pt=newConn->getPointer();
5516   int *ptI=newConnI->getPointer();
5517   ptI[0]=0;
5518   const int *oldc=_nodal_connec->getConstPointer();
5519   const int *ci=_nodal_connec_index->getConstPointer();
5520   for(int i=0;i<nbOfCells;i++,ci++)
5521     {
5522       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5523         {
5524           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5525             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5526           pt=std::copy(tmp,tmp+8,pt);
5527           ptI[1]=ptI[0]+4;
5528           ptI[2]=ptI[0]+8;
5529           *retPt++=i;
5530           *retPt++=i;
5531           ptI+=2;
5532         }
5533       else
5534         {
5535           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5536           ptI[1]=ptI[0]+ci[1]-ci[0];
5537           ptI++;
5538           *retPt++=i;
5539         }
5540     }
5541   _nodal_connec->decrRef();
5542   _nodal_connec=newConn.retn();
5543   _nodal_connec_index->decrRef();
5544   _nodal_connec_index=newConnI.retn();
5545   computeTypes();
5546   updateTime();
5547   return ret.retn();
5548 }
5549
5550 /*!
5551  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5552  */
5553 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5554 {
5555   checkConnectivityFullyDefined();
5556   if(getMeshDimension()!=2)
5557     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5558   int nbOfCells=getNumberOfCells();
5559   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5560   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5561   ret->alloc(nbOfCells+nbOfCutCells,1);
5562   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5563   int *retPt=ret->getPointer();
5564   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5565   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5566   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5567   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5568   int *pt=newConn->getPointer();
5569   int *ptI=newConnI->getPointer();
5570   ptI[0]=0;
5571   const int *oldc=_nodal_connec->getConstPointer();
5572   const int *ci=_nodal_connec_index->getConstPointer();
5573   for(int i=0;i<nbOfCells;i++,ci++)
5574     {
5575       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5576         {
5577           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5578             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5579           pt=std::copy(tmp,tmp+8,pt);
5580           ptI[1]=ptI[0]+4;
5581           ptI[2]=ptI[0]+8;
5582           *retPt++=i;
5583           *retPt++=i;
5584           ptI+=2;
5585         }
5586       else
5587         {
5588           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5589           ptI[1]=ptI[0]+ci[1]-ci[0];
5590           ptI++;
5591           *retPt++=i;
5592         }
5593     }
5594   _nodal_connec->decrRef();
5595   _nodal_connec=newConn.retn();
5596   _nodal_connec_index->decrRef();
5597   _nodal_connec_index=newConnI.retn();
5598   computeTypes();
5599   updateTime();
5600   return ret.retn();
5601 }
5602
5603 /*!
5604  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5605  */
5606 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5607 {
5608   checkConnectivityFullyDefined();
5609   if(getMeshDimension()!=3)
5610     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5611   int nbOfCells=getNumberOfCells();
5612   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5613   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5614   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5615   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5616   int *retPt=ret->getPointer();
5617   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5618   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5619   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5620   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5621   int *pt=newConn->getPointer();
5622   int *ptI=newConnI->getPointer();
5623   ptI[0]=0;
5624   const int *oldc=_nodal_connec->getConstPointer();
5625   const int *ci=_nodal_connec_index->getConstPointer();
5626   for(int i=0;i<nbOfCells;i++,ci++)
5627     {
5628       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5629         {
5630           for(int j=0;j<5;j++,pt+=5,ptI++)
5631             {
5632               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5633               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];
5634               *retPt++=i;
5635               ptI[1]=ptI[0]+5;
5636             }
5637         }
5638       else
5639         {
5640           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5641           ptI[1]=ptI[0]+ci[1]-ci[0];
5642           ptI++;
5643           *retPt++=i;
5644         }
5645     }
5646   _nodal_connec->decrRef();
5647   _nodal_connec=newConn.retn();
5648   _nodal_connec_index->decrRef();
5649   _nodal_connec_index=newConnI.retn();
5650   computeTypes();
5651   updateTime();
5652   return ret.retn();
5653 }
5654
5655 /*!
5656  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5657  */
5658 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5659 {
5660   checkConnectivityFullyDefined();
5661   if(getMeshDimension()!=3)
5662     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5663   int nbOfCells=getNumberOfCells();
5664   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5665   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5666   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5667   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5668   int *retPt=ret->getPointer();
5669   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5670   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5671   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5672   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5673   int *pt=newConn->getPointer();
5674   int *ptI=newConnI->getPointer();
5675   ptI[0]=0;
5676   const int *oldc=_nodal_connec->getConstPointer();
5677   const int *ci=_nodal_connec_index->getConstPointer();
5678   for(int i=0;i<nbOfCells;i++,ci++)
5679     {
5680       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5681         {
5682           for(int j=0;j<6;j++,pt+=5,ptI++)
5683             {
5684               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5685               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];
5686               *retPt++=i;
5687               ptI[1]=ptI[0]+5;
5688             }
5689         }
5690       else
5691         {
5692           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5693           ptI[1]=ptI[0]+ci[1]-ci[0];
5694           ptI++;
5695           *retPt++=i;
5696         }
5697     }
5698   _nodal_connec->decrRef();
5699   _nodal_connec=newConn.retn();
5700   _nodal_connec_index->decrRef();
5701   _nodal_connec_index=newConnI.retn();
5702   computeTypes();
5703   updateTime();
5704   return ret.retn();
5705 }
5706
5707 /*!
5708  * 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.
5709  * This method completly ignore coordinates.
5710  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5711  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5712  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5713  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5714  */
5715 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5716 {
5717   checkFullyDefined();
5718   if(getMeshDimension()!=2)
5719     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5720   int nbOfCells=getNumberOfCells();
5721   int *connI=_nodal_connec_index->getPointer();
5722   int newConnLgth=0;
5723   for(int i=0;i<nbOfCells;i++,connI++)
5724     {
5725       int offset=descIndex[i];
5726       int nbOfEdges=descIndex[i+1]-offset;
5727       //
5728       bool ddirect=desc[offset+nbOfEdges-1]>0;
5729       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5730       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5731       for(int j=0;j<nbOfEdges;j++)
5732         {
5733           bool direct=desc[offset+j]>0;
5734           int edgeId=std::abs(desc[offset+j])-1;
5735           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5736             {
5737               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5738               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5739               int ref2=direct?id1:id2;
5740               if(ref==ref2)
5741                 {
5742                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5743                   newConnLgth+=nbOfSubNodes-1;
5744                   ref=direct?id2:id1;
5745                 }
5746               else
5747                 {
5748                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5749                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5750                 }
5751             }
5752           else
5753             {
5754               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5755             }
5756         }
5757       newConnLgth++;//+1 is for cell type
5758       connI[1]=newConnLgth;
5759     }
5760   //
5761   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5762   newConn->alloc(newConnLgth,1);
5763   int *work=newConn->getPointer();
5764   for(int i=0;i<nbOfCells;i++)
5765     {
5766       *work++=INTERP_KERNEL::NORM_POLYGON;
5767       int offset=descIndex[i];
5768       int nbOfEdges=descIndex[i+1]-offset;
5769       for(int j=0;j<nbOfEdges;j++)
5770         {
5771           bool direct=desc[offset+j]>0;
5772           int edgeId=std::abs(desc[offset+j])-1;
5773           if(direct)
5774             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5775           else
5776             {
5777               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5778               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5779               work=std::copy(it,it+nbOfSubNodes-1,work);
5780             }
5781         }
5782     }
5783   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5784   _types.clear();
5785   if(nbOfCells>0)
5786     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5787 }
5788
5789 /*!
5790  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5791  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5792  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5793  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5794  * so it can be useful to call mergeNodes() before calling this method.
5795  *  \throw If \a this->getMeshDimension() <= 1.
5796  *  \throw If the coordinates array is not set.
5797  *  \throw If the nodal connectivity of cells is not defined.
5798  */
5799 void MEDCouplingUMesh::convertDegeneratedCells()
5800 {
5801   checkFullyDefined();
5802   if(getMeshDimension()<=1)
5803     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5804   int nbOfCells=getNumberOfCells();
5805   if(nbOfCells<1)
5806     return ;
5807   int initMeshLgth=getMeshLength();
5808   int *conn=_nodal_connec->getPointer();
5809   int *index=_nodal_connec_index->getPointer();
5810   int posOfCurCell=0;
5811   int newPos=0;
5812   int lgthOfCurCell;
5813   for(int i=0;i<nbOfCells;i++)
5814     {
5815       lgthOfCurCell=index[i+1]-posOfCurCell;
5816       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5817       int newLgth;
5818       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5819                                                                                                      conn+newPos+1,newLgth);
5820       conn[newPos]=newType;
5821       newPos+=newLgth+1;
5822       posOfCurCell=index[i+1];
5823       index[i+1]=newPos;
5824     }
5825   if(newPos!=initMeshLgth)
5826     _nodal_connec->reAlloc(newPos);
5827   computeTypes();
5828 }
5829
5830 /*!
5831  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5832  * A cell is considered to be oriented correctly if an angle between its
5833  * normal vector and a given vector is less than \c PI / \c 2.
5834  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5835  *         cells. 
5836  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5837  *         checked.
5838  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5839  *         is not cleared before filling in.
5840  *  \throw If \a this->getMeshDimension() != 2.
5841  *  \throw If \a this->getSpaceDimension() != 3.
5842  *
5843  *  \if ENABLE_EXAMPLES
5844  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5845  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5846  *  \endif
5847  */
5848 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5849 {
5850   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5851     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5852   int nbOfCells=getNumberOfCells();
5853   const int *conn=_nodal_connec->getConstPointer();
5854   const int *connI=_nodal_connec_index->getConstPointer();
5855   const double *coordsPtr=_coords->getConstPointer();
5856   for(int i=0;i<nbOfCells;i++)
5857     {
5858       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5859       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5860         {
5861           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5862           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5863             cells.push_back(i);
5864         }
5865     }
5866 }
5867
5868 /*!
5869  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5870  * considered to be oriented correctly if an angle between its normal vector and a
5871  * given vector is less than \c PI / \c 2. 
5872  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5873  *         cells. 
5874  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5875  *         checked.
5876  *  \throw If \a this->getMeshDimension() != 2.
5877  *  \throw If \a this->getSpaceDimension() != 3.
5878  *
5879  *  \if ENABLE_EXAMPLES
5880  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5881  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5882  *  \endif
5883  */
5884 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5885 {
5886   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5887     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5888   int nbOfCells=getNumberOfCells();
5889   int *conn=_nodal_connec->getPointer();
5890   const int *connI=_nodal_connec_index->getConstPointer();
5891   const double *coordsPtr=_coords->getConstPointer();
5892   bool isModified=false;
5893   for(int i=0;i<nbOfCells;i++)
5894     {
5895       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5896       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5897         {
5898           bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5899           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5900             {
5901               isModified=true;
5902               if(!isQuadratic)
5903                 {
5904                   std::vector<int> tmp(connI[i+1]-connI[i]-2);
5905                   std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5906                   std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5907                 }
5908               else
5909                 {
5910                   int sz(((int)(connI[i+1]-connI[i]-1))/2);
5911                   std::vector<int> tmp0(sz-1),tmp1(sz);
5912                   std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5913                   std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5914                   std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5915                   std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5916                 }
5917             }
5918         }
5919     }
5920   if(isModified)
5921     _nodal_connec->declareAsNew();
5922   updateTime();
5923 }
5924
5925 /*!
5926  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5927  * oriented facets. The normal vector of the facet should point out of the cell.
5928  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5929  *         is not cleared before filling in.
5930  *  \throw If \a this->getMeshDimension() != 3.
5931  *  \throw If \a this->getSpaceDimension() != 3.
5932  *  \throw If the coordinates array is not set.
5933  *  \throw If the nodal connectivity of cells is not defined.
5934  *
5935  *  \if ENABLE_EXAMPLES
5936  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5937  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5938  *  \endif
5939  */
5940 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5941 {
5942   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5943     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5944   int nbOfCells=getNumberOfCells();
5945   const int *conn=_nodal_connec->getConstPointer();
5946   const int *connI=_nodal_connec_index->getConstPointer();
5947   const double *coordsPtr=_coords->getConstPointer();
5948   for(int i=0;i<nbOfCells;i++)
5949     {
5950       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5951       if(type==INTERP_KERNEL::NORM_POLYHED)
5952         {
5953           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5954             cells.push_back(i);
5955         }
5956     }
5957 }
5958
5959 /*!
5960  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5961  * out of the cell. 
5962  *  \throw If \a this->getMeshDimension() != 3.
5963  *  \throw If \a this->getSpaceDimension() != 3.
5964  *  \throw If the coordinates array is not set.
5965  *  \throw If the nodal connectivity of cells is not defined.
5966  *  \throw If the reparation fails.
5967  *
5968  *  \if ENABLE_EXAMPLES
5969  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5970  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5971  *  \endif
5972  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5973  */
5974 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5975 {
5976   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5977     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5978   int nbOfCells=getNumberOfCells();
5979   int *conn=_nodal_connec->getPointer();
5980   const int *connI=_nodal_connec_index->getConstPointer();
5981   const double *coordsPtr=_coords->getConstPointer();
5982   for(int i=0;i<nbOfCells;i++)
5983     {
5984       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5985       if(type==INTERP_KERNEL::NORM_POLYHED)
5986         {
5987           try
5988           {
5989               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5990                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5991           }
5992           catch(INTERP_KERNEL::Exception& e)
5993           {
5994               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5995               throw INTERP_KERNEL::Exception(oss.str().c_str());
5996           }
5997         }
5998     }
5999   updateTime();
6000 }
6001
6002 /*!
6003  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6004  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6005  * according to which the first facet of the cell should be oriented to have the normal vector
6006  * pointing out of cell.
6007  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6008  *         cells. The caller is to delete this array using decrRef() as it is no more
6009  *         needed. 
6010  *  \throw If \a this->getMeshDimension() != 3.
6011  *  \throw If \a this->getSpaceDimension() != 3.
6012  *  \throw If the coordinates array is not set.
6013  *  \throw If the nodal connectivity of cells is not defined.
6014  *
6015  *  \if ENABLE_EXAMPLES
6016  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6017  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6018  *  \endif
6019  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6020  */
6021 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6022 {
6023   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6024   if(getMeshDimension()!=3)
6025     throw INTERP_KERNEL::Exception(msg);
6026   int spaceDim=getSpaceDimension();
6027   if(spaceDim!=3)
6028     throw INTERP_KERNEL::Exception(msg);
6029   //
6030   int nbOfCells=getNumberOfCells();
6031   int *conn=_nodal_connec->getPointer();
6032   const int *connI=_nodal_connec_index->getConstPointer();
6033   const double *coo=getCoords()->getConstPointer();
6034   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6035   for(int i=0;i<nbOfCells;i++)
6036     {
6037       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6038       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6039         {
6040           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6041             {
6042               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6043               cells->pushBackSilent(i);
6044             }
6045         }
6046     }
6047   return cells.retn();
6048 }
6049
6050 /*!
6051  * This method is a faster method to correct orientation of all 3D cells in \a this.
6052  * 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.
6053  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6054  * 
6055  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6056  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6057  */
6058 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6059 {
6060   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6061     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6062   int nbOfCells=getNumberOfCells();
6063   int *conn=_nodal_connec->getPointer();
6064   const int *connI=_nodal_connec_index->getConstPointer();
6065   const double *coordsPtr=_coords->getConstPointer();
6066   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6067   for(int i=0;i<nbOfCells;i++)
6068     {
6069       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6070       switch(type)
6071       {
6072         case INTERP_KERNEL::NORM_TETRA4:
6073           {
6074             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6075               {
6076                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6077                 ret->pushBackSilent(i);
6078               }
6079             break;
6080           }
6081         case INTERP_KERNEL::NORM_PYRA5:
6082           {
6083             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6084               {
6085                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6086                 ret->pushBackSilent(i);
6087               }
6088             break;
6089           }
6090         case INTERP_KERNEL::NORM_PENTA6:
6091         case INTERP_KERNEL::NORM_HEXA8:
6092         case INTERP_KERNEL::NORM_HEXGP12:
6093           {
6094             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6095               {
6096                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6097                 ret->pushBackSilent(i);
6098               }
6099             break;
6100           }
6101         case INTERP_KERNEL::NORM_POLYHED:
6102           {
6103             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6104               {
6105                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6106                 ret->pushBackSilent(i);
6107               }
6108             break;
6109           }
6110         default:
6111           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 !");
6112       }
6113     }
6114   updateTime();
6115   return ret.retn();
6116 }
6117
6118 /*!
6119  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6120  * If it is not the case an exception will be thrown.
6121  * This method is fast because the first cell of \a this is used to compute the plane.
6122  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6123  * \param pos output of size at least 3 used to store a point owned of searched plane.
6124  */
6125 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6126 {
6127   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6128     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6129   const int *conn=_nodal_connec->getConstPointer();
6130   const int *connI=_nodal_connec_index->getConstPointer();
6131   const double *coordsPtr=_coords->getConstPointer();
6132   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6133   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6134 }
6135
6136 /*!
6137  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6138  * cells. Currently cells of the following types are treated:
6139  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6140  * For a cell of other type an exception is thrown.
6141  * Space dimension of a 2D mesh can be either 2 or 3.
6142  * The Edge Ratio of a cell \f$t\f$ is: 
6143  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6144  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6145  *  the smallest edge lengths of \f$t\f$.
6146  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6147  *          cells and one time, lying on \a this mesh. The caller is to delete this
6148  *          field using decrRef() as it is no more needed. 
6149  *  \throw If the coordinates array is not set.
6150  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6151  *  \throw If the connectivity data array has more than one component.
6152  *  \throw If the connectivity data array has a named component.
6153  *  \throw If the connectivity index data array has more than one component.
6154  *  \throw If the connectivity index data array has a named component.
6155  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6156  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6157  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6158  */
6159 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6160 {
6161   checkCoherency();
6162   int spaceDim=getSpaceDimension();
6163   int meshDim=getMeshDimension();
6164   if(spaceDim!=2 && spaceDim!=3)
6165     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6166   if(meshDim!=2 && meshDim!=3)
6167     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6168   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6169   ret->setMesh(this);
6170   int nbOfCells=getNumberOfCells();
6171   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6172   arr->alloc(nbOfCells,1);
6173   double *pt=arr->getPointer();
6174   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6175   const int *conn=_nodal_connec->getConstPointer();
6176   const int *connI=_nodal_connec_index->getConstPointer();
6177   const double *coo=_coords->getConstPointer();
6178   double tmp[12];
6179   for(int i=0;i<nbOfCells;i++,pt++)
6180     {
6181       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6182       switch(t)
6183       {
6184         case INTERP_KERNEL::NORM_TRI3:
6185           {
6186             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6187             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6188             break;
6189           }
6190         case INTERP_KERNEL::NORM_QUAD4:
6191           {
6192             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6193             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6194             break;
6195           }
6196         case INTERP_KERNEL::NORM_TETRA4:
6197           {
6198             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6199             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6200             break;
6201           }
6202         default:
6203           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6204       }
6205       conn+=connI[i+1]-connI[i];
6206     }
6207   ret->setName("EdgeRatio");
6208   ret->synchronizeTimeWithSupport();
6209   return ret.retn();
6210 }
6211
6212 /*!
6213  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6214  * cells. Currently cells of the following types are treated:
6215  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6216  * For a cell of other type an exception is thrown.
6217  * Space dimension of a 2D mesh can be either 2 or 3.
6218  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6219  *          cells and one time, lying on \a this mesh. The caller is to delete this
6220  *          field using decrRef() as it is no more needed. 
6221  *  \throw If the coordinates array is not set.
6222  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6223  *  \throw If the connectivity data array has more than one component.
6224  *  \throw If the connectivity data array has a named component.
6225  *  \throw If the connectivity index data array has more than one component.
6226  *  \throw If the connectivity index data array has a named component.
6227  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6228  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6229  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6230  */
6231 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6232 {
6233   checkCoherency();
6234   int spaceDim=getSpaceDimension();
6235   int meshDim=getMeshDimension();
6236   if(spaceDim!=2 && spaceDim!=3)
6237     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6238   if(meshDim!=2 && meshDim!=3)
6239     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6240   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6241   ret->setMesh(this);
6242   int nbOfCells=getNumberOfCells();
6243   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6244   arr->alloc(nbOfCells,1);
6245   double *pt=arr->getPointer();
6246   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6247   const int *conn=_nodal_connec->getConstPointer();
6248   const int *connI=_nodal_connec_index->getConstPointer();
6249   const double *coo=_coords->getConstPointer();
6250   double tmp[12];
6251   for(int i=0;i<nbOfCells;i++,pt++)
6252     {
6253       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6254       switch(t)
6255       {
6256         case INTERP_KERNEL::NORM_TRI3:
6257           {
6258             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6259             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6260             break;
6261           }
6262         case INTERP_KERNEL::NORM_QUAD4:
6263           {
6264             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6265             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6266             break;
6267           }
6268         case INTERP_KERNEL::NORM_TETRA4:
6269           {
6270             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6271             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6272             break;
6273           }
6274         default:
6275           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6276       }
6277       conn+=connI[i+1]-connI[i];
6278     }
6279   ret->setName("AspectRatio");
6280   ret->synchronizeTimeWithSupport();
6281   return ret.retn();
6282 }
6283
6284 /*!
6285  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6286  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6287  * treated: INTERP_KERNEL::NORM_QUAD4.
6288  * For a cell of other type an exception is thrown.
6289  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6290  *          cells and one time, lying on \a this mesh. The caller is to delete this
6291  *          field using decrRef() as it is no more needed. 
6292  *  \throw If the coordinates array is not set.
6293  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6294  *  \throw If the connectivity data array has more than one component.
6295  *  \throw If the connectivity data array has a named component.
6296  *  \throw If the connectivity index data array has more than one component.
6297  *  \throw If the connectivity index data array has a named component.
6298  *  \throw If \a this->getMeshDimension() != 2.
6299  *  \throw If \a this->getSpaceDimension() != 3.
6300  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6301  */
6302 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6303 {
6304   checkCoherency();
6305   int spaceDim=getSpaceDimension();
6306   int meshDim=getMeshDimension();
6307   if(spaceDim!=3)
6308     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6309   if(meshDim!=2)
6310     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6311   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6312   ret->setMesh(this);
6313   int nbOfCells=getNumberOfCells();
6314   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6315   arr->alloc(nbOfCells,1);
6316   double *pt=arr->getPointer();
6317   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6318   const int *conn=_nodal_connec->getConstPointer();
6319   const int *connI=_nodal_connec_index->getConstPointer();
6320   const double *coo=_coords->getConstPointer();
6321   double tmp[12];
6322   for(int i=0;i<nbOfCells;i++,pt++)
6323     {
6324       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6325       switch(t)
6326       {
6327         case INTERP_KERNEL::NORM_QUAD4:
6328           {
6329             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6330             *pt=INTERP_KERNEL::quadWarp(tmp);
6331             break;
6332           }
6333         default:
6334           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6335       }
6336       conn+=connI[i+1]-connI[i];
6337     }
6338   ret->setName("Warp");
6339   ret->synchronizeTimeWithSupport();
6340   return ret.retn();
6341 }
6342
6343
6344 /*!
6345  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6346  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6347  * treated: INTERP_KERNEL::NORM_QUAD4.
6348  * For a cell of other type an exception is thrown.
6349  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6350  *          cells and one time, lying on \a this mesh. The caller is to delete this
6351  *          field using decrRef() as it is no more needed. 
6352  *  \throw If the coordinates array is not set.
6353  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6354  *  \throw If the connectivity data array has more than one component.
6355  *  \throw If the connectivity data array has a named component.
6356  *  \throw If the connectivity index data array has more than one component.
6357  *  \throw If the connectivity index data array has a named component.
6358  *  \throw If \a this->getMeshDimension() != 2.
6359  *  \throw If \a this->getSpaceDimension() != 3.
6360  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6361  */
6362 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6363 {
6364   checkCoherency();
6365   int spaceDim=getSpaceDimension();
6366   int meshDim=getMeshDimension();
6367   if(spaceDim!=3)
6368     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6369   if(meshDim!=2)
6370     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6371   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6372   ret->setMesh(this);
6373   int nbOfCells=getNumberOfCells();
6374   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6375   arr->alloc(nbOfCells,1);
6376   double *pt=arr->getPointer();
6377   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6378   const int *conn=_nodal_connec->getConstPointer();
6379   const int *connI=_nodal_connec_index->getConstPointer();
6380   const double *coo=_coords->getConstPointer();
6381   double tmp[12];
6382   for(int i=0;i<nbOfCells;i++,pt++)
6383     {
6384       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6385       switch(t)
6386       {
6387         case INTERP_KERNEL::NORM_QUAD4:
6388           {
6389             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6390             *pt=INTERP_KERNEL::quadSkew(tmp);
6391             break;
6392           }
6393         default:
6394           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6395       }
6396       conn+=connI[i+1]-connI[i];
6397     }
6398   ret->setName("Skew");
6399   ret->synchronizeTimeWithSupport();
6400   return ret.retn();
6401 }
6402
6403 /*!
6404  * This method aggregate the bbox of each cell and put it into bbox parameter.
6405  * 
6406  * \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)
6407  *                         For all other cases this input parameter is ignored.
6408  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6409  * 
6410  * \throw If \a this is not fully set (coordinates and connectivity).
6411  * \throw If a cell in \a this has no valid nodeId.
6412  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6413  */
6414 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6415 {
6416   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6417   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.
6418     return getBoundingBoxForBBTreeFast();
6419   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6420     {
6421       bool presenceOfQuadratic(false);
6422       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6423         {
6424           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6425           if(cm.isQuadratic())
6426             presenceOfQuadratic=true;
6427         }
6428       if(!presenceOfQuadratic)
6429         return getBoundingBoxForBBTreeFast();
6430       if(mDim==2 && sDim==2)
6431         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6432       else
6433         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6434     }
6435   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) !");
6436 }
6437
6438 /*!
6439  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6440  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6441  * 
6442  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6443  * 
6444  * \throw If \a this is not fully set (coordinates and connectivity).
6445  * \throw If a cell in \a this has no valid nodeId.
6446  */
6447 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6448 {
6449   checkFullyDefined();
6450   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6451   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6452   double *bbox(ret->getPointer());
6453   for(int i=0;i<nbOfCells*spaceDim;i++)
6454     {
6455       bbox[2*i]=std::numeric_limits<double>::max();
6456       bbox[2*i+1]=-std::numeric_limits<double>::max();
6457     }
6458   const double *coordsPtr(_coords->getConstPointer());
6459   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6460   for(int i=0;i<nbOfCells;i++)
6461     {
6462       int offset=connI[i]+1;
6463       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6464       for(int j=0;j<nbOfNodesForCell;j++)
6465         {
6466           int nodeId=conn[offset+j];
6467           if(nodeId>=0 && nodeId<nbOfNodes)
6468             {
6469               for(int k=0;k<spaceDim;k++)
6470                 {
6471                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6472                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6473                 }
6474               kk++;
6475             }
6476         }
6477       if(kk==0)
6478         {
6479           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6480           throw INTERP_KERNEL::Exception(oss.str().c_str());
6481         }
6482     }
6483   return ret.retn();
6484 }
6485
6486 /*!
6487  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6488  * useful for 2D meshes having quadratic cells
6489  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6490  * the two extremities of the arc of circle).
6491  * 
6492  * \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)
6493  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6494  * \throw If \a this is not fully defined.
6495  * \throw If \a this is not a mesh with meshDimension equal to 2.
6496  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6497  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6498  */
6499 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6500 {
6501   checkFullyDefined();
6502   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6503   if(spaceDim!=2 || mDim!=2)
6504     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!");
6505   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6506   double *bbox(ret->getPointer());
6507   const double *coords(_coords->getConstPointer());
6508   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6509   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6510     {
6511       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6512       int sz(connI[1]-connI[0]-1);
6513       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6514       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6515       INTERP_KERNEL::QuadraticPolygon *pol(0);
6516       for(int j=0;j<sz;j++)
6517         {
6518           int nodeId(conn[*connI+1+j]);
6519           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6520         }
6521       if(!cm.isQuadratic())
6522         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6523       else
6524         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6525       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6526       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6527     }
6528   return ret.retn();
6529 }
6530
6531 /*!
6532  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6533  * useful for 2D meshes having quadratic cells
6534  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6535  * the two extremities of the arc of circle).
6536  * 
6537  * \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)
6538  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6539  * \throw If \a this is not fully defined.
6540  * \throw If \a this is not a mesh with meshDimension equal to 1.
6541  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6542  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6543  */
6544 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6545 {
6546   checkFullyDefined();
6547   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6548   if(spaceDim!=2 || mDim!=1)
6549     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!");
6550   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6551   double *bbox(ret->getPointer());
6552   const double *coords(_coords->getConstPointer());
6553   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6554   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6555     {
6556       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6557       int sz(connI[1]-connI[0]-1);
6558       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6559       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6560       INTERP_KERNEL::Edge *edge(0);
6561       for(int j=0;j<sz;j++)
6562         {
6563           int nodeId(conn[*connI+1+j]);
6564           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6565         }
6566       if(!cm.isQuadratic())
6567         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6568       else
6569         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6570       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6571       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6572     }
6573   return ret.retn();
6574 }
6575
6576 /// @cond INTERNAL
6577
6578 namespace ParaMEDMEMImpl
6579 {
6580   class ConnReader
6581   {
6582   public:
6583     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6584     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6585   private:
6586     const int *_conn;
6587     int _val;
6588   };
6589
6590   class ConnReader2
6591   {
6592   public:
6593     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6594     bool operator() (const int& pos) { return _conn[pos]==_val; }
6595   private:
6596     const int *_conn;
6597     int _val;
6598   };
6599 }
6600
6601 /// @endcond
6602
6603 /*!
6604  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6605  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6606  * \a this is composed in cell types.
6607  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6608  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6609  * This parameter is kept only for compatibility with other methode listed above.
6610  */
6611 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6612 {
6613   checkConnectivityFullyDefined();
6614   const int *conn=_nodal_connec->getConstPointer();
6615   const int *connI=_nodal_connec_index->getConstPointer();
6616   const int *work=connI;
6617   int nbOfCells=getNumberOfCells();
6618   std::size_t n=getAllGeoTypes().size();
6619   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6620   std::set<INTERP_KERNEL::NormalizedCellType> types;
6621   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6622     {
6623       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6624       if(types.find(typ)!=types.end())
6625         {
6626           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6627           oss << " is not contiguous !";
6628           throw INTERP_KERNEL::Exception(oss.str().c_str());
6629         }
6630       types.insert(typ);
6631       ret[3*i]=typ;
6632       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6633       ret[3*i+1]=(int)std::distance(work,work2);
6634       work=work2;
6635     }
6636   return ret;
6637 }
6638
6639 /*!
6640  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6641  * only for types cell, type node is not managed.
6642  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6643  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6644  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6645  * If 2 or more same geometric type is in \a code and exception is thrown too.
6646  *
6647  * This method firstly checks
6648  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6649  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6650  * an exception is thrown too.
6651  * 
6652  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6653  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6654  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6655  */
6656 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6657 {
6658   if(code.empty())
6659     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6660   std::size_t sz=code.size();
6661   std::size_t n=sz/3;
6662   if(sz%3!=0)
6663     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6664   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6665   int nb=0;
6666   bool isNoPflUsed=true;
6667   for(std::size_t i=0;i<n;i++)
6668     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6669       {
6670         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6671         nb+=code[3*i+1];
6672         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6673           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6674         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6675       }
6676   if(types.size()!=n)
6677     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6678   if(isNoPflUsed)
6679     {
6680       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6681         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6682       if(types.size()==_types.size())
6683         return 0;
6684     }
6685   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6686   ret->alloc(nb,1);
6687   int *retPtr=ret->getPointer();
6688   const int *connI=_nodal_connec_index->getConstPointer();
6689   const int *conn=_nodal_connec->getConstPointer();
6690   int nbOfCells=getNumberOfCells();
6691   const int *i=connI;
6692   int kk=0;
6693   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6694     {
6695       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6696       int offset=(int)std::distance(connI,i);
6697       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6698       int nbOfCellsOfCurType=(int)std::distance(i,j);
6699       if(code[3*kk+2]==-1)
6700         for(int k=0;k<nbOfCellsOfCurType;k++)
6701           *retPtr++=k+offset;
6702       else
6703         {
6704           int idInIdsPerType=code[3*kk+2];
6705           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6706             {
6707               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6708               if(zePfl)
6709                 {
6710                   zePfl->checkAllocated();
6711                   if(zePfl->getNumberOfComponents()==1)
6712                     {
6713                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6714                         {
6715                           if(*k>=0 && *k<nbOfCellsOfCurType)
6716                             *retPtr=(*k)+offset;
6717                           else
6718                             {
6719                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6720                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6721                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6722                             }
6723                         }
6724                     }
6725                   else
6726                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6727                 }
6728               else
6729                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6730             }
6731           else
6732             {
6733               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6734               oss << " should be in [0," << idsPerType.size() << ") !";
6735               throw INTERP_KERNEL::Exception(oss.str().c_str());
6736             }
6737         }
6738       i=j;
6739     }
6740   return ret.retn();
6741 }
6742
6743 /*!
6744  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6745  * 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.
6746  * 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.
6747  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6748  * 
6749  * \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.
6750  * \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,
6751  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6752  * \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.
6753  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6754  * \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
6755  */
6756 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6757 {
6758   if(!profile)
6759     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6760   if(profile->getNumberOfComponents()!=1)
6761     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6762   checkConnectivityFullyDefined();
6763   const int *conn=_nodal_connec->getConstPointer();
6764   const int *connI=_nodal_connec_index->getConstPointer();
6765   int nbOfCells=getNumberOfCells();
6766   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6767   std::vector<int> typeRangeVals(1);
6768   for(const int *i=connI;i!=connI+nbOfCells;)
6769     {
6770       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6771       if(std::find(types.begin(),types.end(),curType)!=types.end())
6772         {
6773           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6774         }
6775       types.push_back(curType);
6776       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6777       typeRangeVals.push_back((int)std::distance(connI,i));
6778     }
6779   //
6780   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6781   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6782   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6783   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6784   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6785   //
6786   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6787   code.resize(3*nbOfCastsFinal);
6788   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6789   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6790   for(int i=0;i<nbOfCastsFinal;i++)
6791     {
6792       int castId=castsPresent->getIJ(i,0);
6793       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6794       idsInPflPerType2.push_back(tmp3);
6795       code[3*i]=(int)types[castId];
6796       code[3*i+1]=tmp3->getNumberOfTuples();
6797       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6798       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6799         {
6800           tmp4->copyStringInfoFrom(*profile);
6801           idsPerType2.push_back(tmp4);
6802           code[3*i+2]=(int)idsPerType2.size()-1;
6803         }
6804       else
6805         {
6806           code[3*i+2]=-1;
6807         }
6808     }
6809   std::size_t sz2=idsInPflPerType2.size();
6810   idsInPflPerType.resize(sz2);
6811   for(std::size_t i=0;i<sz2;i++)
6812     {
6813       DataArrayInt *locDa=idsInPflPerType2[i];
6814       locDa->incrRef();
6815       idsInPflPerType[i]=locDa;
6816     }
6817   std::size_t sz=idsPerType2.size();
6818   idsPerType.resize(sz);
6819   for(std::size_t i=0;i<sz;i++)
6820     {
6821       DataArrayInt *locDa=idsPerType2[i];
6822       locDa->incrRef();
6823       idsPerType[i]=locDa;
6824     }
6825 }
6826
6827 /*!
6828  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6829  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6830  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6831  * 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.
6832  */
6833 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6834 {
6835   checkFullyDefined();
6836   nM1LevMesh->checkFullyDefined();
6837   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6838     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6839   if(_coords!=nM1LevMesh->getCoords())
6840     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6841   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6842   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6843   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6844   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6845   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6846   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6847   tmp->setConnectivity(tmp0,tmp1);
6848   tmp->renumberCells(ret0->getConstPointer(),false);
6849   revDesc=tmp->getNodalConnectivity();
6850   revDescIndx=tmp->getNodalConnectivityIndex();
6851   DataArrayInt *ret=0;
6852   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6853     {
6854       int tmp2;
6855       ret->getMaxValue(tmp2);
6856       ret->decrRef();
6857       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6858       throw INTERP_KERNEL::Exception(oss.str().c_str());
6859     }
6860   nM1LevMeshIds=ret;
6861   //
6862   revDesc->incrRef();
6863   revDescIndx->incrRef();
6864   ret1->incrRef();
6865   ret0->incrRef();
6866   meshnM1Old2New=ret0;
6867   return ret1;
6868 }
6869
6870 /*!
6871  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6872  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6873  * in "Old to New" mode.
6874  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6875  *          this array using decrRef() as it is no more needed.
6876  *  \throw If the nodal connectivity of cells is not defined.
6877  */
6878 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6879 {
6880   checkConnectivityFullyDefined();
6881   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6882   renumberCells(ret->getConstPointer(),false);
6883   return ret.retn();
6884 }
6885
6886 /*!
6887  * This methods checks that cells are sorted by their types.
6888  * This method makes asumption (no check) that connectivity is correctly set before calling.
6889  */
6890 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6891 {
6892   checkFullyDefined();
6893   const int *conn=_nodal_connec->getConstPointer();
6894   const int *connI=_nodal_connec_index->getConstPointer();
6895   int nbOfCells=getNumberOfCells();
6896   std::set<INTERP_KERNEL::NormalizedCellType> types;
6897   for(const int *i=connI;i!=connI+nbOfCells;)
6898     {
6899       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6900       if(types.find(curType)!=types.end())
6901         return false;
6902       types.insert(curType);
6903       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6904     }
6905   return true;
6906 }
6907
6908 /*!
6909  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6910  * The geometric type order is specified by MED file.
6911  * 
6912  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6913  */
6914 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6915 {
6916   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6917 }
6918
6919 /*!
6920  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6921  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6922  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6923  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6924  */
6925 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6926 {
6927   checkFullyDefined();
6928   const int *conn=_nodal_connec->getConstPointer();
6929   const int *connI=_nodal_connec_index->getConstPointer();
6930   int nbOfCells=getNumberOfCells();
6931   if(nbOfCells==0)
6932     return true;
6933   int lastPos=-1;
6934   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6935   for(const int *i=connI;i!=connI+nbOfCells;)
6936     {
6937       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6938       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6939       if(isTypeExists!=orderEnd)
6940         {
6941           int pos=(int)std::distance(orderBg,isTypeExists);
6942           if(pos<=lastPos)
6943             return false;
6944           lastPos=pos;
6945           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6946         }
6947       else
6948         {
6949           if(sg.find(curType)==sg.end())
6950             {
6951               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6952               sg.insert(curType);
6953             }
6954           else
6955             return false;
6956         }
6957     }
6958   return true;
6959 }
6960
6961 /*!
6962  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6963  * 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
6964  * 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'.
6965  */
6966 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6967 {
6968   checkConnectivityFullyDefined();
6969   int nbOfCells=getNumberOfCells();
6970   const int *conn=_nodal_connec->getConstPointer();
6971   const int *connI=_nodal_connec_index->getConstPointer();
6972   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6973   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6974   tmpa->alloc(nbOfCells,1);
6975   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6976   tmpb->fillWithZero();
6977   int *tmp=tmpa->getPointer();
6978   int *tmp2=tmpb->getPointer();
6979   for(const int *i=connI;i!=connI+nbOfCells;i++)
6980     {
6981       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6982       if(where!=orderEnd)
6983         {
6984           int pos=(int)std::distance(orderBg,where);
6985           tmp2[pos]++;
6986           tmp[std::distance(connI,i)]=pos;
6987         }
6988       else
6989         {
6990           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6991           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6992           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6993           throw INTERP_KERNEL::Exception(oss.str().c_str());
6994         }
6995     }
6996   nbPerType=tmpb.retn();
6997   return tmpa.retn();
6998 }
6999
7000 /*!
7001  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7002  *
7003  * \return a new object containing the old to new correspondance.
7004  *
7005  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7006  */
7007 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7008 {
7009   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7010 }
7011
7012 /*!
7013  * 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.
7014  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7015  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7016  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7017  */
7018 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7019 {
7020   DataArrayInt *nbPerType=0;
7021   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7022   nbPerType->decrRef();
7023   return tmpa->buildPermArrPerLevel();
7024 }
7025
7026 /*!
7027  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7028  * The number of cells remains unchanged after the call of this method.
7029  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7030  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7031  *
7032  * \return the array giving the correspondance old to new.
7033  */
7034 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7035 {
7036   checkFullyDefined();
7037   computeTypes();
7038   const int *conn=_nodal_connec->getConstPointer();
7039   const int *connI=_nodal_connec_index->getConstPointer();
7040   int nbOfCells=getNumberOfCells();
7041   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7042   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7043     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7044       {
7045         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7046         types.push_back(curType);
7047         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7048       }
7049   DataArrayInt *ret=DataArrayInt::New();
7050   ret->alloc(nbOfCells,1);
7051   int *retPtr=ret->getPointer();
7052   std::fill(retPtr,retPtr+nbOfCells,-1);
7053   int newCellId=0;
7054   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7055     {
7056       for(const int *i=connI;i!=connI+nbOfCells;i++)
7057         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7058           retPtr[std::distance(connI,i)]=newCellId++;
7059     }
7060   renumberCells(retPtr,false);
7061   return ret;
7062 }
7063
7064 /*!
7065  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7066  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7067  * This method makes asumption that connectivity is correctly set before calling.
7068  */
7069 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7070 {
7071   checkConnectivityFullyDefined();
7072   const int *conn=_nodal_connec->getConstPointer();
7073   const int *connI=_nodal_connec_index->getConstPointer();
7074   int nbOfCells=getNumberOfCells();
7075   std::vector<MEDCouplingUMesh *> ret;
7076   for(const int *i=connI;i!=connI+nbOfCells;)
7077     {
7078       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7079       int beginCellId=(int)std::distance(connI,i);
7080       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7081       int endCellId=(int)std::distance(connI,i);
7082       int sz=endCellId-beginCellId;
7083       int *cells=new int[sz];
7084       for(int j=0;j<sz;j++)
7085         cells[j]=beginCellId+j;
7086       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7087       delete [] cells;
7088       ret.push_back(m);
7089     }
7090   return ret;
7091 }
7092
7093 /*!
7094  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7095  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7096  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7097  *
7098  * \return a newly allocated instance, that the caller must manage.
7099  * \throw If \a this contains more than one geometric type.
7100  * \throw If the nodal connectivity of \a this is not fully defined.
7101  * \throw If the internal data is not coherent.
7102  */
7103 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7104 {
7105   checkConnectivityFullyDefined();
7106   if(_types.size()!=1)
7107     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7108   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7109   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7110   ret->setCoords(getCoords());
7111   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7112   if(retC)
7113     {
7114       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7115       retC->setNodalConnectivity(c);
7116     }
7117   else
7118     {
7119       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7120       if(!retD)
7121         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7122       DataArrayInt *c=0,*ci=0;
7123       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7124       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7125       retD->setNodalConnectivity(cs,cis);
7126     }
7127   return ret.retn();
7128 }
7129
7130 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7131 {
7132   checkConnectivityFullyDefined();
7133   if(_types.size()!=1)
7134     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7135   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7136   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7137   if(cm.isDynamic())
7138     {
7139       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7140       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7141       throw INTERP_KERNEL::Exception(oss.str().c_str());
7142     }
7143   int nbCells=getNumberOfCells();
7144   int typi=(int)typ;
7145   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7146   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7147   int *outPtr=connOut->getPointer();
7148   const int *conn=_nodal_connec->begin();
7149   const int *connI=_nodal_connec_index->begin();
7150   nbNodesPerCell++;
7151   for(int i=0;i<nbCells;i++,connI++)
7152     {
7153       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7154         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7155       else
7156         {
7157           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 << ") !";
7158           throw INTERP_KERNEL::Exception(oss.str().c_str());
7159         }
7160     }
7161   return connOut.retn();
7162 }
7163
7164 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7165 {
7166   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7167   checkConnectivityFullyDefined();
7168   if(_types.size()!=1)
7169     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7170   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7171   if(lgth<nbCells)
7172     throw INTERP_KERNEL::Exception(msg0);
7173   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7174   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7175   int *cp(c->getPointer()),*cip(ci->getPointer());
7176   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7177   cip[0]=0;
7178   for(int i=0;i<nbCells;i++,cip++,incip++)
7179     {
7180       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7181       int delta(stop-strt);
7182       if(delta>=1)
7183         {
7184           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7185             cp=std::copy(incp+strt,incp+stop,cp);
7186           else
7187             throw INTERP_KERNEL::Exception(msg0);
7188         }
7189       else
7190         throw INTERP_KERNEL::Exception(msg0);
7191       cip[1]=cip[0]+delta;
7192     }
7193   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7194 }
7195
7196 /*!
7197  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7198  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7199  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7200  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7201  * are not used here to avoid the build of big permutation array.
7202  *
7203  * \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
7204  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7205  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7206  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7207  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7208  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7209  * \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
7210  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7211  */
7212 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7213                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7214                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7215 {
7216   std::vector<const MEDCouplingUMesh *> ms2;
7217   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7218     if(*it)
7219       {
7220         (*it)->checkConnectivityFullyDefined();
7221         ms2.push_back(*it);
7222       }
7223   if(ms2.empty())
7224     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7225   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7226   int meshDim=ms2[0]->getMeshDimension();
7227   std::vector<const MEDCouplingUMesh *> m1ssm;
7228   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7229   //
7230   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7231   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7232   int fake=0,rk=0;
7233   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7234   ret1->alloc(0,1); ret2->alloc(0,1);
7235   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7236     {
7237       if(meshDim!=(*it)->getMeshDimension())
7238         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7239       if(refCoo!=(*it)->getCoords())
7240         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7241       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7242       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7243       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7244       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7245         {
7246           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7247           m1ssmSingleAuto.push_back(singleCell);
7248           m1ssmSingle.push_back(singleCell);
7249           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7250         }
7251     }
7252   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7253   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7254   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7255   for(std::size_t i=0;i<m1ssm.size();i++)
7256     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7257   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7258   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7259   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7260   return ret0.retn();
7261 }
7262
7263 /*!
7264  * This method returns a newly created DataArrayInt instance.
7265  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7266  */
7267 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7268 {
7269   checkFullyDefined();
7270   const int *conn=_nodal_connec->getConstPointer();
7271   const int *connIndex=_nodal_connec_index->getConstPointer();
7272   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7273   for(const int *w=begin;w!=end;w++)
7274     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7275       ret->pushBackSilent(*w);
7276   return ret.retn();
7277 }
7278
7279 /*!
7280  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7281  * are in [0:getNumberOfCells())
7282  */
7283 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7284 {
7285   checkFullyDefined();
7286   const int *conn=_nodal_connec->getConstPointer();
7287   const int *connI=_nodal_connec_index->getConstPointer();
7288   int nbOfCells=getNumberOfCells();
7289   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7290   int *tmp=new int[nbOfCells];
7291   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7292     {
7293       int j=0;
7294       for(const int *i=connI;i!=connI+nbOfCells;i++)
7295         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7296           tmp[std::distance(connI,i)]=j++;
7297     }
7298   DataArrayInt *ret=DataArrayInt::New();
7299   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7300   ret->copyStringInfoFrom(*da);
7301   int *retPtr=ret->getPointer();
7302   const int *daPtr=da->getConstPointer();
7303   int nbOfElems=da->getNbOfElems();
7304   for(int k=0;k<nbOfElems;k++)
7305     retPtr[k]=tmp[daPtr[k]];
7306   delete [] tmp;
7307   return ret;
7308 }
7309
7310 /*!
7311  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7312  * This method \b works \b for mesh sorted by type.
7313  * cells whose ids is in 'idsPerGeoType' array.
7314  * This method conserves coords and name of mesh.
7315  */
7316 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7317 {
7318   std::vector<int> code=getDistributionOfTypes();
7319   std::size_t nOfTypesInThis=code.size()/3;
7320   int sz=0,szOfType=0;
7321   for(std::size_t i=0;i<nOfTypesInThis;i++)
7322     {
7323       if(code[3*i]!=type)
7324         sz+=code[3*i+1];
7325       else
7326         szOfType=code[3*i+1];
7327     }
7328   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7329     if(*work<0 || *work>=szOfType)
7330       {
7331         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7332         oss << ". It should be in [0," << szOfType << ") !";
7333         throw INTERP_KERNEL::Exception(oss.str().c_str());
7334       }
7335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7336   int *idsPtr=idsTokeep->getPointer();
7337   int offset=0;
7338   for(std::size_t i=0;i<nOfTypesInThis;i++)
7339     {
7340       if(code[3*i]!=type)
7341         for(int j=0;j<code[3*i+1];j++)
7342           *idsPtr++=offset+j;
7343       else
7344         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7345       offset+=code[3*i+1];
7346     }
7347   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7348   ret->copyTinyInfoFrom(this);
7349   return ret.retn();
7350 }
7351
7352 /*!
7353  * This method returns a vector of size 'this->getNumberOfCells()'.
7354  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7355  */
7356 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7357 {
7358   int ncell=getNumberOfCells();
7359   std::vector<bool> ret(ncell);
7360   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7361   const int *c=getNodalConnectivity()->getConstPointer();
7362   for(int i=0;i<ncell;i++)
7363     {
7364       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7365       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7366       ret[i]=cm.isQuadratic();
7367     }
7368   return ret;
7369 }
7370
7371 /*!
7372  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7373  */
7374 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7375 {
7376   if(other->getType()!=UNSTRUCTURED)
7377     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7378   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7379   return MergeUMeshes(this,otherC);
7380 }
7381
7382 /*!
7383  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7384  * computed by averaging coordinates of cell nodes, so this method is not a right
7385  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7386  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7387  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7388  *          components. The caller is to delete this array using decrRef() as it is
7389  *          no more needed.
7390  *  \throw If the coordinates array is not set.
7391  *  \throw If the nodal connectivity of cells is not defined.
7392  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7393  */
7394 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7395 {
7396   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7397   int spaceDim=getSpaceDimension();
7398   int nbOfCells=getNumberOfCells();
7399   ret->alloc(nbOfCells,spaceDim);
7400   ret->copyStringInfoFrom(*getCoords());
7401   double *ptToFill=ret->getPointer();
7402   const int *nodal=_nodal_connec->getConstPointer();
7403   const int *nodalI=_nodal_connec_index->getConstPointer();
7404   const double *coor=_coords->getConstPointer();
7405   for(int i=0;i<nbOfCells;i++)
7406     {
7407       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7408       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7409       ptToFill+=spaceDim;
7410     }
7411   return ret.retn();
7412 }
7413
7414 /*!
7415  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7416  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7417  * 
7418  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7419  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7420  * 
7421  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7422  * \throw If \a this is not fully defined (coordinates and connectivity)
7423  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7424  */
7425 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7426 {
7427   checkFullyDefined();
7428   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7429   int spaceDim=getSpaceDimension();
7430   int nbOfCells=getNumberOfCells();
7431   int nbOfNodes=getNumberOfNodes();
7432   ret->alloc(nbOfCells,spaceDim);
7433   double *ptToFill=ret->getPointer();
7434   const int *nodal=_nodal_connec->getConstPointer();
7435   const int *nodalI=_nodal_connec_index->getConstPointer();
7436   const double *coor=_coords->getConstPointer();
7437   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7438     {
7439       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7440       std::fill(ptToFill,ptToFill+spaceDim,0.);
7441       if(type!=INTERP_KERNEL::NORM_POLYHED)
7442         {
7443           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7444             {
7445               if(*conn>=0 && *conn<nbOfNodes)
7446                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7447               else
7448                 {
7449                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7450                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7451                 }
7452             }
7453           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7454           if(nbOfNodesInCell>0)
7455             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7456           else
7457             {
7458               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7459               throw INTERP_KERNEL::Exception(oss.str().c_str());
7460             }
7461         }
7462       else
7463         {
7464           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7465           s.erase(-1);
7466           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7467             {
7468               if(*it>=0 && *it<nbOfNodes)
7469                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7470               else
7471                 {
7472                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7473                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7474                 }
7475             }
7476           if(!s.empty())
7477             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7478           else
7479             {
7480               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7481               throw INTERP_KERNEL::Exception(oss.str().c_str());
7482             }
7483         }
7484     }
7485   return ret.retn();
7486 }
7487
7488 /*!
7489  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7490  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7491  * are specified via an array of cell ids. 
7492  *  \warning Validity of the specified cell ids is not checked! 
7493  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7494  *  \param [in] begin - an array of cell ids of interest.
7495  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7496  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7497  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7498  *          caller is to delete this array using decrRef() as it is no more needed. 
7499  *  \throw If the coordinates array is not set.
7500  *  \throw If the nodal connectivity of cells is not defined.
7501  *
7502  *  \if ENABLE_EXAMPLES
7503  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7504  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7505  *  \endif
7506  */
7507 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7508 {
7509   DataArrayDouble *ret=DataArrayDouble::New();
7510   int spaceDim=getSpaceDimension();
7511   int nbOfTuple=(int)std::distance(begin,end);
7512   ret->alloc(nbOfTuple,spaceDim);
7513   double *ptToFill=ret->getPointer();
7514   double *tmp=new double[spaceDim];
7515   const int *nodal=_nodal_connec->getConstPointer();
7516   const int *nodalI=_nodal_connec_index->getConstPointer();
7517   const double *coor=_coords->getConstPointer();
7518   for(const int *w=begin;w!=end;w++)
7519     {
7520       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7521       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7522       ptToFill+=spaceDim;
7523     }
7524   delete [] tmp;
7525   return ret;
7526 }
7527
7528 /*!
7529  * 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".
7530  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7531  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7532  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7533  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7534  * 
7535  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7536  * \throw If spaceDim!=3 or meshDim!=2.
7537  * \throw If connectivity of \a this is invalid.
7538  * \throw If connectivity of a cell in \a this points to an invalid node.
7539  */
7540 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7541 {
7542   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7543   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7544   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7545     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7546   ret->alloc(nbOfCells,4);
7547   double *retPtr(ret->getPointer());
7548   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7549   const double *coor(_coords->begin());
7550   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7551     {
7552       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7553       if(nodalI[1]-nodalI[0]>=3)
7554         {
7555           for(int j=0;j<3;j++)
7556             {
7557               int nodeId(nodal[nodalI[0]+1+j]);
7558               if(nodeId>=0 && nodeId<nbOfNodes)
7559                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7560               else
7561                 {
7562                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7563                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7564                 }
7565             }
7566         }
7567       else
7568         {
7569           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7570           throw INTERP_KERNEL::Exception(oss.str().c_str());
7571         }
7572       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7573       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7574     }
7575   return ret.retn();
7576 }
7577
7578 /*!
7579  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7580  * 
7581  */
7582 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7583 {
7584   if(!da)
7585     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7586   da->checkAllocated();
7587   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7588   ret->setCoords(da);
7589   int nbOfTuples=da->getNumberOfTuples();
7590   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7591   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7592   c->alloc(2*nbOfTuples,1);
7593   cI->alloc(nbOfTuples+1,1);
7594   int *cp=c->getPointer();
7595   int *cip=cI->getPointer();
7596   *cip++=0;
7597   for(int i=0;i<nbOfTuples;i++)
7598     {
7599       *cp++=INTERP_KERNEL::NORM_POINT1;
7600       *cp++=i;
7601       *cip++=2*(i+1);
7602     }
7603   ret->setConnectivity(c,cI,true);
7604   return ret.retn();
7605 }
7606 /*!
7607  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7608  * Cells and nodes of
7609  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7610  *  \param [in] mesh1 - the first mesh.
7611  *  \param [in] mesh2 - the second mesh.
7612  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7613  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7614  *          is no more needed.
7615  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7616  *  \throw If the coordinates array is not set in none of the meshes.
7617  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7618  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7619  */
7620 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7621 {
7622   std::vector<const MEDCouplingUMesh *> tmp(2);
7623   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7624   return MergeUMeshes(tmp);
7625 }
7626
7627 /*!
7628  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7629  * Cells and nodes of
7630  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7631  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7632  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7633  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7634  *          is no more needed.
7635  *  \throw If \a a.size() == 0.
7636  *  \throw If \a a[ *i* ] == NULL.
7637  *  \throw If the coordinates array is not set in none of the meshes.
7638  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7639  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7640  */
7641 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7642 {
7643   std::size_t sz=a.size();
7644   if(sz==0)
7645     return MergeUMeshesLL(a);
7646   for(std::size_t ii=0;ii<sz;ii++)
7647     if(!a[ii])
7648       {
7649         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7650         throw INTERP_KERNEL::Exception(oss.str().c_str());
7651       }
7652   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7653   std::vector< const MEDCouplingUMesh * > aa(sz);
7654   int spaceDim=-3;
7655   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7656     {
7657       const MEDCouplingUMesh *cur=a[i];
7658       const DataArrayDouble *coo=cur->getCoords();
7659       if(coo)
7660         spaceDim=coo->getNumberOfComponents();
7661     }
7662   if(spaceDim==-3)
7663     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7664   for(std::size_t i=0;i<sz;i++)
7665     {
7666       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7667       aa[i]=bb[i];
7668     }
7669   return MergeUMeshesLL(aa);
7670 }
7671
7672 /// @cond INTERNAL
7673
7674 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7675 {
7676   if(a.empty())
7677     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7678   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7679   int meshDim=(*it)->getMeshDimension();
7680   int nbOfCells=(*it)->getNumberOfCells();
7681   int meshLgth=(*it++)->getMeshLength();
7682   for(;it!=a.end();it++)
7683     {
7684       if(meshDim!=(*it)->getMeshDimension())
7685         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7686       nbOfCells+=(*it)->getNumberOfCells();
7687       meshLgth+=(*it)->getMeshLength();
7688     }
7689   std::vector<const MEDCouplingPointSet *> aps(a.size());
7690   std::copy(a.begin(),a.end(),aps.begin());
7691   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7692   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7693   ret->setCoords(pts);
7694   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7695   c->alloc(meshLgth,1);
7696   int *cPtr=c->getPointer();
7697   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7698   cI->alloc(nbOfCells+1,1);
7699   int *cIPtr=cI->getPointer();
7700   *cIPtr++=0;
7701   int offset=0;
7702   int offset2=0;
7703   for(it=a.begin();it!=a.end();it++)
7704     {
7705       int curNbOfCell=(*it)->getNumberOfCells();
7706       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7707       const int *curC=(*it)->_nodal_connec->getConstPointer();
7708       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7709       for(int j=0;j<curNbOfCell;j++)
7710         {
7711           const int *src=curC+curCI[j];
7712           *cPtr++=*src++;
7713           for(;src!=curC+curCI[j+1];src++,cPtr++)
7714             {
7715               if(*src!=-1)
7716                 *cPtr=*src+offset2;
7717               else
7718                 *cPtr=-1;
7719             }
7720         }
7721       offset+=curCI[curNbOfCell];
7722       offset2+=(*it)->getNumberOfNodes();
7723     }
7724   //
7725   ret->setConnectivity(c,cI,true);
7726   return ret.retn();
7727 }
7728
7729 /// @endcond
7730
7731 /*!
7732  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7733  * dimension and sharing the node coordinates array.
7734  * All cells of the first mesh precede all cells of the second mesh
7735  * within the result mesh. 
7736  *  \param [in] mesh1 - the first mesh.
7737  *  \param [in] mesh2 - the second mesh.
7738  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7739  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7740  *          is no more needed.
7741  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7742  *  \throw If the meshes do not share the node coordinates array.
7743  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7744  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7745  */
7746 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7747 {
7748   std::vector<const MEDCouplingUMesh *> tmp(2);
7749   tmp[0]=mesh1; tmp[1]=mesh2;
7750   return MergeUMeshesOnSameCoords(tmp);
7751 }
7752
7753 /*!
7754  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7755  * dimension and sharing the node coordinates array.
7756  * All cells of the *i*-th mesh precede all cells of the
7757  * (*i*+1)-th mesh within the result mesh.
7758  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7759  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7760  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7761  *          is no more needed.
7762  *  \throw If \a a.size() == 0.
7763  *  \throw If \a a[ *i* ] == NULL.
7764  *  \throw If the meshes do not share the node coordinates array.
7765  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7766  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7767  */
7768 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7769 {
7770   if(meshes.empty())
7771     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7772   for(std::size_t ii=0;ii<meshes.size();ii++)
7773     if(!meshes[ii])
7774       {
7775         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7776         throw INTERP_KERNEL::Exception(oss.str().c_str());
7777       }
7778   const DataArrayDouble *coords=meshes.front()->getCoords();
7779   int meshDim=meshes.front()->getMeshDimension();
7780   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7781   int meshLgth=0;
7782   int meshIndexLgth=0;
7783   for(;iter!=meshes.end();iter++)
7784     {
7785       if(coords!=(*iter)->getCoords())
7786         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7787       if(meshDim!=(*iter)->getMeshDimension())
7788         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7789       meshLgth+=(*iter)->getMeshLength();
7790       meshIndexLgth+=(*iter)->getNumberOfCells();
7791     }
7792   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7793   nodal->alloc(meshLgth,1);
7794   int *nodalPtr=nodal->getPointer();
7795   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7796   nodalIndex->alloc(meshIndexLgth+1,1);
7797   int *nodalIndexPtr=nodalIndex->getPointer();
7798   int offset=0;
7799   for(iter=meshes.begin();iter!=meshes.end();iter++)
7800     {
7801       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7802       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7803       int nbOfCells=(*iter)->getNumberOfCells();
7804       int meshLgth2=(*iter)->getMeshLength();
7805       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7806       if(iter!=meshes.begin())
7807         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7808       else
7809         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7810       offset+=meshLgth2;
7811     }
7812   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7813   ret->setName("merge");
7814   ret->setMeshDimension(meshDim);
7815   ret->setConnectivity(nodal,nodalIndex,true);
7816   ret->setCoords(coords);
7817   return ret;
7818 }
7819
7820 /*!
7821  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7822  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7823  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7824  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7825  * New" mode are returned for each input mesh.
7826  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7827  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7828  *          valid values [0,1,2], see zipConnectivityTraducer().
7829  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7830  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7831  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7832  *          no more needed.
7833  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7834  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7835  *          is no more needed.
7836  *  \throw If \a meshes.size() == 0.
7837  *  \throw If \a meshes[ *i* ] == NULL.
7838  *  \throw If the meshes do not share the node coordinates array.
7839  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7840  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7841  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7842  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7843  */
7844 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7845 {
7846   //All checks are delegated to MergeUMeshesOnSameCoords
7847   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7848   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7849   corr.resize(meshes.size());
7850   std::size_t nbOfMeshes=meshes.size();
7851   int offset=0;
7852   const int *o2nPtr=o2n->getConstPointer();
7853   for(std::size_t i=0;i<nbOfMeshes;i++)
7854     {
7855       DataArrayInt *tmp=DataArrayInt::New();
7856       int curNbOfCells=meshes[i]->getNumberOfCells();
7857       tmp->alloc(curNbOfCells,1);
7858       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7859       offset+=curNbOfCells;
7860       tmp->setName(meshes[i]->getName());
7861       corr[i]=tmp;
7862     }
7863   return ret.retn();
7864 }
7865
7866 /*!
7867  * Makes all given meshes share the nodal connectivity array. The common connectivity
7868  * array is created by concatenating the connectivity arrays of all given meshes. All
7869  * the given meshes must be of the same space dimension but dimension of cells **can
7870  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7871  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7872  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7873  *  \param [in,out] meshes - a vector of meshes to update.
7874  *  \throw If any of \a meshes is NULL.
7875  *  \throw If the coordinates array is not set in any of \a meshes.
7876  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7877  *  \throw If \a meshes are of different space dimension.
7878  */
7879 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7880 {
7881   std::size_t sz=meshes.size();
7882   if(sz==0 || sz==1)
7883     return;
7884   std::vector< const DataArrayDouble * > coords(meshes.size());
7885   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7886   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7887     {
7888       if((*it))
7889         {
7890           (*it)->checkConnectivityFullyDefined();
7891           const DataArrayDouble *coo=(*it)->getCoords();
7892           if(coo)
7893             *it2=coo;
7894           else
7895             {
7896               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7897               oss << " has no coordinate array defined !";
7898               throw INTERP_KERNEL::Exception(oss.str().c_str());
7899             }
7900         }
7901       else
7902         {
7903           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7904           oss << " is null !";
7905           throw INTERP_KERNEL::Exception(oss.str().c_str());
7906         }
7907     }
7908   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7909   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7910   int offset=(*it)->getNumberOfNodes();
7911   (*it++)->setCoords(res);
7912   for(;it!=meshes.end();it++)
7913     {
7914       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7915       (*it)->setCoords(res);
7916       (*it)->shiftNodeNumbersInConn(offset);
7917       offset+=oldNumberOfNodes;
7918     }
7919 }
7920
7921 /*!
7922  * Merges nodes coincident with a given precision within all given meshes that share
7923  * the nodal connectivity array. The given meshes **can be of different** mesh
7924  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7925  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7926  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7927  *  \param [in,out] meshes - a vector of meshes to update.
7928  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7929  *  \throw If any of \a meshes is NULL.
7930  *  \throw If the \a meshes do not share the same node coordinates array.
7931  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7932  */
7933 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7934 {
7935   if(meshes.empty())
7936     return ;
7937   std::set<const DataArrayDouble *> s;
7938   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7939     {
7940       if(*it)
7941         s.insert((*it)->getCoords());
7942       else
7943         {
7944           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 !";
7945           throw INTERP_KERNEL::Exception(oss.str().c_str());
7946         }
7947     }
7948   if(s.size()!=1)
7949     {
7950       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 !";
7951       throw INTERP_KERNEL::Exception(oss.str().c_str());
7952     }
7953   const DataArrayDouble *coo=*(s.begin());
7954   if(!coo)
7955     return;
7956   //
7957   DataArrayInt *comm,*commI;
7958   coo->findCommonTuples(eps,-1,comm,commI);
7959   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7960   int oldNbOfNodes=coo->getNumberOfTuples();
7961   int newNbOfNodes;
7962   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7963   if(oldNbOfNodes==newNbOfNodes)
7964     return ;
7965   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7966   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7967     {
7968       (*it)->renumberNodesInConn(o2n->getConstPointer());
7969       (*it)->setCoords(newCoords);
7970     } 
7971 }
7972
7973 /*!
7974  * 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.
7975  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7976  * \param isQuad specifies the policy of connectivity.
7977  * @ret in/out parameter in which the result will be append
7978  */
7979 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7980 {
7981   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7982   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7983   ret.push_back(cm.getExtrudedType());
7984   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7985   switch(flatType)
7986   {
7987     case INTERP_KERNEL::NORM_POINT1:
7988       {
7989         ret.push_back(connBg[1]);
7990         ret.push_back(connBg[1]+nbOfNodesPerLev);
7991         break;
7992       }
7993     case INTERP_KERNEL::NORM_SEG2:
7994       {
7995         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7996         ret.insert(ret.end(),conn,conn+4);
7997         break;
7998       }
7999     case INTERP_KERNEL::NORM_SEG3:
8000       {
8001         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8002         ret.insert(ret.end(),conn,conn+8);
8003         break;
8004       }
8005     case INTERP_KERNEL::NORM_QUAD4:
8006       {
8007         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8008         ret.insert(ret.end(),conn,conn+8);
8009         break;
8010       }
8011     case INTERP_KERNEL::NORM_TRI3:
8012       {
8013         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8014         ret.insert(ret.end(),conn,conn+6);
8015         break;
8016       }
8017     case INTERP_KERNEL::NORM_TRI6:
8018       {
8019         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,
8020           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8021         ret.insert(ret.end(),conn,conn+15);
8022         break;
8023       }
8024     case INTERP_KERNEL::NORM_QUAD8:
8025       {
8026         int conn[20]={
8027           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8028           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8029           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8030         };
8031         ret.insert(ret.end(),conn,conn+20);
8032         break;
8033       }
8034     case INTERP_KERNEL::NORM_POLYGON:
8035       {
8036         std::back_insert_iterator< std::vector<int> > ii(ret);
8037         std::copy(connBg+1,connEnd,ii);
8038         *ii++=-1;
8039         std::reverse_iterator<const int *> rConnBg(connEnd);
8040         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8041         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8042         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8043         for(std::size_t i=0;i<nbOfRadFaces;i++)
8044           {
8045             *ii++=-1;
8046             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8047             std::copy(conn,conn+4,ii);
8048           }
8049         break;
8050       }
8051     default:
8052       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8053   }
8054 }
8055
8056 /*!
8057  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8058  */
8059 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8060 {
8061   std::size_t i, ip1;
8062   double v[3]={0.,0.,0.};
8063   std::size_t sz=std::distance(begin,end);
8064   if(isQuadratic)
8065     sz/=2;
8066   for(i=0;i<sz;i++)
8067     {
8068       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];
8069       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8070       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8071     }
8072   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8073
8074   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8075   // SEG3 forming a circle):
8076   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8077     {
8078       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8079       for(std::size_t j=0;j<sz;j++)
8080         {
8081           if (j%2)  // current point i is quadratic, next point i+1 is standard
8082             {
8083               i = sz+j;
8084               ip1 = (j+1)%sz; // ip1 = "i+1"
8085             }
8086           else      // current point i is standard, next point i+1 is quadratic
8087             {
8088               i = j;
8089               ip1 = j+sz;
8090             }
8091           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8092           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8093           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8094         }
8095       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8096     }
8097   return (ret>0.);
8098 }
8099
8100 /*!
8101  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8102  */
8103 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8104 {
8105   std::vector<std::pair<int,int> > edges;
8106   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8107   const int *bgFace=begin;
8108   for(std::size_t i=0;i<nbOfFaces;i++)
8109     {
8110       const int *endFace=std::find(bgFace+1,end,-1);
8111       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8112       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8113         {
8114           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8115           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8116             return false;
8117           edges.push_back(p1);
8118         }
8119       bgFace=endFace+1;
8120     }
8121   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8122 }
8123
8124 /*!
8125  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8126  */
8127 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8128 {
8129   double vec0[3],vec1[3];
8130   std::size_t sz=std::distance(begin,end);
8131   if(sz%2!=0)
8132     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8133   int nbOfNodes=(int)sz/2;
8134   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8135   const double *pt0=coords+3*begin[0];
8136   const double *pt1=coords+3*begin[nbOfNodes];
8137   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8138   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8139 }
8140
8141 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8142 {
8143   std::size_t sz=std::distance(begin,end);
8144   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8145   std::size_t nbOfNodes(sz/2);
8146   std::copy(begin,end,(int *)tmp);
8147   for(std::size_t j=1;j<nbOfNodes;j++)
8148     {
8149       begin[j]=tmp[nbOfNodes-j];
8150       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8151     }
8152 }
8153
8154 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8155 {
8156   std::size_t sz=std::distance(begin,end);
8157   if(sz!=4)
8158     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8159   double vec0[3],vec1[3];
8160   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8161   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]; 
8162   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;
8163 }
8164
8165 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8166 {
8167   std::size_t sz=std::distance(begin,end);
8168   if(sz!=5)
8169     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8170   double vec0[3];
8171   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8172   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8173   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8174 }
8175
8176 /*!
8177  * 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 ) 
8178  * 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
8179  * a 2D space.
8180  *
8181  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8182  * \param [in] coords the coordinates with nb of components exactly equal to 3
8183  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8184  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8185  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8186  */
8187 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8188 {
8189   int nbFaces=std::count(begin+1,end,-1)+1;
8190   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8191   double *vPtr=v->getPointer();
8192   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8193   double *pPtr=p->getPointer();
8194   const int *stFaceConn=begin+1;
8195   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8196     {
8197       const int *endFaceConn=std::find(stFaceConn,end,-1);
8198       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8199       stFaceConn=endFaceConn+1;
8200     }
8201   pPtr=p->getPointer(); vPtr=v->getPointer();
8202   DataArrayInt *comm1=0,*commI1=0;
8203   v->findCommonTuples(eps,-1,comm1,commI1);
8204   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8205   const int *comm1Ptr=comm1->getConstPointer();
8206   const int *commI1Ptr=commI1->getConstPointer();
8207   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8208   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8209   //
8210   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8211   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8212   mm->finishInsertingCells();
8213   //
8214   for(int i=0;i<nbOfGrps1;i++)
8215     {
8216       int vecId=comm1Ptr[commI1Ptr[i]];
8217       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8218       DataArrayInt *comm2=0,*commI2=0;
8219       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8220       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8221       const int *comm2Ptr=comm2->getConstPointer();
8222       const int *commI2Ptr=commI2->getConstPointer();
8223       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8224       for(int j=0;j<nbOfGrps2;j++)
8225         {
8226           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8227             {
8228               res->insertAtTheEnd(begin,end);
8229               res->pushBackSilent(-1);
8230             }
8231           else
8232             {
8233               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8234               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8235               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8236               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8237               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8238               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8239               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8240               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8241               const int *idsNodePtr=idsNode->getConstPointer();
8242               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];
8243               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8244               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8245               if(std::abs(norm)>eps)
8246                 {
8247                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8248                   mm3->rotate(center,vec,angle);
8249                 }
8250               mm3->changeSpaceDimension(2);
8251               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8252               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8253               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8254               int nbOfCells=mm4->getNumberOfCells();
8255               for(int k=0;k<nbOfCells;k++)
8256                 {
8257                   int l=0;
8258                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8259                     res->pushBackSilent(idsNodePtr[*work]);
8260                   res->pushBackSilent(-1);
8261                 }
8262             }
8263         }
8264     }
8265   res->popBackSilent();
8266 }
8267
8268 /*!
8269  * 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
8270  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8271  * 
8272  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8273  * \param [in] coords coordinates expected to have 3 components.
8274  * \param [in] begin start of the nodal connectivity of the face.
8275  * \param [in] end end of the nodal connectivity (excluded) of the face.
8276  * \param [out] v the normalized vector of size 3
8277  * \param [out] p the pos of plane
8278  */
8279 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8280 {
8281   std::size_t nbPoints=std::distance(begin,end);
8282   if(nbPoints<3)
8283     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8284   double vec[3]={0.,0.,0.};
8285   std::size_t j=0;
8286   bool refFound=false;
8287   for(;j<nbPoints-1 && !refFound;j++)
8288     {
8289       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8290       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8291       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8292       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8293       if(norm>eps)
8294         {
8295           refFound=true;
8296           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8297         }
8298     }
8299   for(std::size_t i=j;i<nbPoints-1;i++)
8300     {
8301       double curVec[3];
8302       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8303       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8304       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8305       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8306       if(norm<eps)
8307         continue;
8308       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8309       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];
8310       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8311       if(norm>eps)
8312         {
8313           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8314           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8315           return ;
8316         }
8317     }
8318   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8319 }
8320
8321 /*!
8322  * This method tries to obtain a well oriented polyhedron.
8323  * If the algorithm fails, an exception will be thrown.
8324  */
8325 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8326 {
8327   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8328   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8329   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8330   isPerm[0]=true;
8331   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8332   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8333   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8334   //
8335   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8336     {
8337       bgFace=begin;
8338       std::size_t smthChanged=0;
8339       for(std::size_t i=0;i<nbOfFaces;i++)
8340         {
8341           endFace=std::find(bgFace+1,end,-1);
8342           nbOfEdgesInFace=std::distance(bgFace,endFace);
8343           if(!isPerm[i])
8344             {
8345               bool b;
8346               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8347                 {
8348                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8349                   std::pair<int,int> p2(p1.second,p1.first);
8350                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8351                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8352                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8353                 }
8354               if(isPerm[i])
8355                 { 
8356                   if(!b)
8357                     std::reverse(bgFace+1,endFace);
8358                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8359                     {
8360                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8361                       std::pair<int,int> p2(p1.second,p1.first);
8362                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8363                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8364                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8365                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8366                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8367                       if(it!=edgesOK.end())
8368                         {
8369                           edgesOK.erase(it);
8370                           edgesFinished.push_back(p1);
8371                         }
8372                       else
8373                         edgesOK.push_back(p1);
8374                     }
8375                 }
8376             }
8377           bgFace=endFace+1;
8378         }
8379       if(smthChanged==0)
8380         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8381     }
8382   if(!edgesOK.empty())
8383     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8384   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8385     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8386       bgFace=begin;
8387       for(std::size_t i=0;i<nbOfFaces;i++)
8388         {
8389           endFace=std::find(bgFace+1,end,-1);
8390           std::reverse(bgFace+1,endFace);
8391           bgFace=endFace+1;
8392         }
8393     }
8394 }
8395
8396 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8397 {
8398   int nbOfNodesExpected(skin->getNumberOfNodes());
8399   const int *n2oPtr(n2o->getConstPointer());
8400   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8401   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8402   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8403   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8404   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8405   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8406   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8407   if(nbOfNodesExpected<1)
8408     return ret.retn();
8409   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8410   *work++=n2oPtr[prevNode];
8411   for(int i=1;i<nbOfNodesExpected;i++)
8412     {
8413       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8414         {
8415           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8416           conn.erase(prevNode);
8417           if(conn.size()==1)
8418             {
8419               int curNode(*(conn.begin()));
8420               *work++=n2oPtr[curNode];
8421               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8422               shar.erase(prevCell);
8423               if(shar.size()==1)
8424                 {
8425                   prevCell=*(shar.begin());
8426                   prevNode=curNode;
8427                 }
8428               else
8429                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8430             }
8431           else
8432             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8433         }
8434       else
8435         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8436     }
8437   return ret.retn();
8438 }
8439
8440 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8441 {
8442   int nbOfNodesExpected(skin->getNumberOfNodes());
8443   int nbOfTurn(nbOfNodesExpected/2);
8444   const int *n2oPtr(n2o->getConstPointer());
8445   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8446   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8447   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8448   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8449   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8450   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8451   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8452   if(nbOfNodesExpected<1)
8453     return ret.retn();
8454   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8455   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8456   for(int i=1;i<nbOfTurn;i++)
8457     {
8458       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8459         {
8460           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8461           conn.erase(prevNode);
8462           if(conn.size()==1)
8463             {
8464               int curNode(*(conn.begin()));
8465               *work=n2oPtr[curNode];
8466               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8467               shar.erase(prevCell);
8468               if(shar.size()==1)
8469                 {
8470                   int curCell(*(shar.begin()));
8471                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8472                   prevCell=curCell;
8473                   prevNode=curNode;
8474                   work++;
8475                 }
8476               else
8477                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8478             }
8479           else
8480             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8481         }
8482       else
8483         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8484     }
8485   return ret.retn();
8486 }
8487
8488 /*!
8489  * This method makes the assumption spacedimension == meshdimension == 2.
8490  * This method works only for linear cells.
8491  * 
8492  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8493  */
8494 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8495 {
8496   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8497     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8498   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8499   int oldNbOfNodes(skin->getNumberOfNodes());
8500   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8501   int nbOfNodesExpected(skin->getNumberOfNodes());
8502   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8503   int nbCells(skin->getNumberOfCells());
8504   if(nbCells==nbOfNodesExpected)
8505     return buildUnionOf2DMeshLinear(skin,n2o);
8506   else if(2*nbCells==nbOfNodesExpected)
8507     return buildUnionOf2DMeshQuadratic(skin,n2o);
8508   else
8509     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8510 }
8511
8512 /*!
8513  * This method makes the assumption spacedimension == meshdimension == 3.
8514  * This method works only for linear cells.
8515  * 
8516  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8517  */
8518 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8519 {
8520   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8521     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8522   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8523   const int *conn=m->getNodalConnectivity()->getConstPointer();
8524   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8525   int nbOfCells=m->getNumberOfCells();
8526   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8527   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8528   if(nbOfCells<1)
8529     return ret.retn();
8530   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8531   for(int i=1;i<nbOfCells;i++)
8532     {
8533       *work++=-1;
8534       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8535     }
8536   return ret.retn();
8537 }
8538
8539 /*!
8540  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8541  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8542  */
8543 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8544 {
8545   double *w=zipFrmt;
8546   if(spaceDim==3)
8547     for(int i=0;i<nbOfNodesInCell;i++)
8548       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8549   else if(spaceDim==2)
8550     {
8551       for(int i=0;i<nbOfNodesInCell;i++)
8552         {
8553           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8554           *w++=0.;
8555         }
8556     }
8557   else
8558     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8559 }
8560
8561 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8562 {
8563   int nbOfCells=getNumberOfCells();
8564   if(nbOfCells<=0)
8565     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8566   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};
8567   ofs << "  <" << getVTKDataSetType() << ">\n";
8568   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8569   ofs << "      <PointData>\n" << pointData << std::endl;
8570   ofs << "      </PointData>\n";
8571   ofs << "      <CellData>\n" << cellData << std::endl;
8572   ofs << "      </CellData>\n";
8573   ofs << "      <Points>\n";
8574   if(getSpaceDimension()==3)
8575     _coords->writeVTK(ofs,8,"Points",byteData);
8576   else
8577     {
8578       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8579       coo->writeVTK(ofs,8,"Points",byteData);
8580     }
8581   ofs << "      </Points>\n";
8582   ofs << "      <Cells>\n";
8583   const int *cPtr=_nodal_connec->getConstPointer();
8584   const int *cIPtr=_nodal_connec_index->getConstPointer();
8585   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8586   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8587   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8588   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8589   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8590   int szFaceOffsets=0,szConn=0;
8591   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8592     {
8593       *w2=cPtr[cIPtr[i]];
8594       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8595         {
8596           *w1=-1;
8597           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8598           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8599         }
8600       else
8601         {
8602           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8603           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8604           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8605           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8606           w4=std::copy(c.begin(),c.end(),w4);
8607         }
8608     }
8609   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8610   types->writeVTK(ofs,8,"UInt8","types",byteData);
8611   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8612   if(szFaceOffsets!=0)
8613     {//presence of Polyhedra
8614       connectivity->reAlloc(szConn);
8615       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8616       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8617       w1=faces->getPointer();
8618       for(int i=0;i<nbOfCells;i++)
8619         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8620           {
8621             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8622             *w1++=nbFaces;
8623             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8624             for(int j=0;j<nbFaces;j++)
8625               {
8626                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8627                 *w1++=(int)std::distance(w6,w5);
8628                 w1=std::copy(w6,w5,w1);
8629                 w6=w5+1;
8630               }
8631           }
8632       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8633     }
8634   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8635   ofs << "      </Cells>\n";
8636   ofs << "    </Piece>\n";
8637   ofs << "  </" << getVTKDataSetType() << ">\n";
8638 }
8639
8640 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8641 {
8642   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8643   if(_mesh_dim==-2)
8644     { stream << " Not set !"; return ; }
8645   stream << " Mesh dimension : " << _mesh_dim << ".";
8646   if(_mesh_dim==-1)
8647     return ;
8648   if(!_coords)
8649     { stream << " No coordinates set !"; return ; }
8650   if(!_coords->isAllocated())
8651     { stream << " Coordinates set but not allocated !"; return ; }
8652   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8653   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8654   if(!_nodal_connec_index)
8655     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8656   if(!_nodal_connec_index->isAllocated())
8657     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8658   int lgth=_nodal_connec_index->getNumberOfTuples();
8659   int cpt=_nodal_connec_index->getNumberOfComponents();
8660   if(cpt!=1 || lgth<1)
8661     return ;
8662   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8663 }
8664
8665 std::string MEDCouplingUMesh::getVTKDataSetType() const
8666 {
8667   return std::string("UnstructuredGrid");
8668 }
8669
8670 std::string MEDCouplingUMesh::getVTKFileExtension() const
8671 {
8672   return std::string("vtu");
8673 }
8674
8675 /*!
8676  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8677  * returns a result mesh constituted by polygons.
8678  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8679  * all nodes from m2.
8680  * The meshes should be in 2D space. In
8681  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8682  * meshes.
8683  *  \param [in] m1 - the first input mesh which is a partitioned object.
8684  *  \param [in] m2 - the second input mesh which is a partition tool.
8685  *  \param [in] eps - precision used to detect coincident mesh entities.
8686  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8687  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8688  *         this array using decrRef() as it is no more needed.
8689  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8690  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8691  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8692  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8693  *         it is no more needed.  
8694  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8695  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8696  *         is no more needed.  
8697  *  \throw If the coordinates array is not set in any of the meshes.
8698  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8699  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8700  */
8701 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8702                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8703 {
8704   m1->checkFullyDefined();
8705   m2->checkFullyDefined();
8706   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8707     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8708
8709   // Step 1: compute all edge intersections (new nodes)
8710   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8711   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8712   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8713   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8714   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8715   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8716   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8717                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8718                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8719   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8720   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8721   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8722
8723   // Step 2: re-order newly created nodes according to the ordering found in m2
8724   std::vector< std::vector<int> > intersectEdge2;
8725   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8726   subDiv2.clear(); dd5=0; dd6=0;
8727
8728   // Step 3:
8729   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8730   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8731   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8732                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8733
8734   // Step 4: Prepare final result:
8735   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8736   addCooDa->alloc((int)(addCoo.size())/2,2);
8737   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8738   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8739   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8740   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8741   std::vector<const DataArrayDouble *> coordss(4);
8742   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8743   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8744   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8745   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8746   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8747   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8748   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8749   ret->setConnectivity(conn,connI,true);
8750   ret->setCoords(coo);
8751   cellNb1=c1.retn(); cellNb2=c2.retn();
8752   return ret.retn();
8753 }
8754
8755
8756 /**
8757  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
8758  * (newly created) nodes corresponding to the edge intersections.
8759  * Output params:
8760  * @param[out] cr, crI connectivity of the resulting mesh
8761  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
8762  * TODO: describe input parameters
8763  */
8764 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8765                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8766                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8767                                                          const std::vector<double>& addCoords,
8768                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8769 {
8770   static const int SPACEDIM=2;
8771   const double *coo1=m1->getCoords()->getConstPointer();
8772   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8773   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8774   int offset1=m1->getNumberOfNodes();
8775   const double *coo2=m2->getCoords()->getConstPointer();
8776   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8777   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8778   int offset2=offset1+m2->getNumberOfNodes();
8779   int offset3=offset2+((int)addCoords.size())/2;
8780   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8781   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8782   // Here a BBTree on 2D-cells, not on segments:
8783   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8784   int ncell1=m1->getNumberOfCells();
8785   crI.push_back(0);
8786   for(int i=0;i<ncell1;i++)
8787     {
8788       std::vector<int> candidates2;
8789       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8790       std::map<INTERP_KERNEL::Node *,int> mapp;
8791       std::map<int,INTERP_KERNEL::Node *> mappRev;
8792       INTERP_KERNEL::QuadraticPolygon pol1;
8793       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8794       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8795       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
8796       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8797       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
8798       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8799           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8800       //
8801       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
8802       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8803       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8804       for(it1.first();!it1.finished();it1.next())
8805         edges1.insert(it1.current()->getPtr());
8806       //
8807       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
8808       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8809       int ii=0;
8810       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8811         {
8812           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8813           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8814           // Complete mapping with elements coming from the current cell it2 in mesh2:
8815           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8816           // pol2 is the new QP in the final merged result.
8817           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8818               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
8819         }
8820       ii=0;
8821       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8822         {
8823           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
8824           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8825           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8826           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8827         }
8828       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
8829       // by m2 but that we still want to keep in the final result.
8830       if(!edges1.empty())
8831         {
8832           try
8833           {
8834               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8835           }
8836           catch(INTERP_KERNEL::Exception& e)
8837           {
8838               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();
8839               throw INTERP_KERNEL::Exception(oss.str().c_str());
8840           }
8841         }
8842       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8843         (*it).second->decrRef();
8844     }
8845 }
8846
8847 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8848 {
8849   std::map<INTERP_KERNEL::Node *,int>::const_iterator it(m.find(n));
8850   if(it==m.end())
8851     throw INTERP_KERNEL::Exception("Internal error in remapping !");
8852   int v((*it).second);
8853   if(v==forbVal0 || v==forbVal1)
8854     return ;
8855   if(std::find(isect.begin(),isect.end(),v)==isect.end())
8856     isect.push_back(v);
8857 }
8858
8859 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8860 {
8861   int sz(c.size());
8862   if(sz<=1)
8863     return false;
8864   bool presenceOfOn(false);
8865   for(int i=0;i<sz;i++)
8866     {
8867       INTERP_KERNEL::ElementaryEdge *e(c[i]);
8868       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
8869         continue ;
8870       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
8871       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
8872     }
8873   return presenceOfOn;
8874 }
8875
8876 /**
8877  * 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.
8878  * 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.
8879  * 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.
8880  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
8881  *
8882  * \return int - the number of new nodes created (in most of cases 0).
8883  * 
8884  * \throw If \a this is not coherent.
8885  * \throw If \a this has not spaceDim equal to 2.
8886  * \throw If \a this has not meshDim equal to 2.
8887  * \throw If some subcells needed to be split are orphan.
8888  * \sa MEDCouplingUMesh::conformize2D
8889  */
8890 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
8891 {
8892   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
8893     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
8894   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
8895   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
8896     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
8897   if(midOpt==0 && midOptI==0)
8898     {
8899       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
8900       return 0;
8901     }
8902   else if(midOpt!=0 && midOptI!=0)
8903     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
8904   else
8905     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
8906 }
8907
8908 /*!
8909  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
8910  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
8911  * 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
8912  * 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).
8913  * 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.
8914  * 
8915  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
8916  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
8917  *
8918  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
8919  * This method expects that all nodes in \a this are not closer than \a eps.
8920  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
8921  * 
8922  * \param [in] eps the relative error to detect merged edges.
8923  * \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
8924  *                           that the user is expected to deal with.
8925  *
8926  * \throw If \a this is not coherent.
8927  * \throw If \a this has not spaceDim equal to 2.
8928  * \throw If \a this has not meshDim equal to 2.
8929  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
8930  */
8931 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
8932 {
8933   static const int SPACEDIM=2;
8934   checkCoherency();
8935   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
8936     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
8937   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
8938   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
8939   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
8940   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
8941   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
8942   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
8943   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
8944   std::vector<double> addCoo;
8945   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
8946   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8947   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8948   for(int i=0;i<nDescCell;i++)
8949     {
8950       std::vector<int> candidates;
8951       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
8952       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8953         if(*it>i)
8954           {
8955             std::map<INTERP_KERNEL::Node *,int> m;
8956             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
8957                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
8958             INTERP_KERNEL::MergePoints merge;
8959             INTERP_KERNEL::QuadraticPolygon c1,c2;
8960             e1->intersectWith(e2,merge,c1,c2);
8961             e1->decrRef(); e2->decrRef();
8962             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
8963               overlapEdge[i].push_back(*it);
8964             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
8965               overlapEdge[*it].push_back(i);
8966             for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
8967               (*it2).first->decrRef();
8968           }
8969     }
8970   // splitting done. sort intersect point in intersectEdge.
8971   std::vector< std::vector<int> > middle(nDescCell);
8972   int nbOf2DCellsToBeSplit(0);
8973   bool middleNeedsToBeUsed(false);
8974   std::vector<bool> cells2DToTreat(nDescCell,false);
8975   for(int i=0;i<nDescCell;i++)
8976     {
8977       std::vector<int>& isect(intersectEdge[i]);
8978       int sz((int)isect.size());
8979       if(sz>1)
8980         {
8981           std::map<INTERP_KERNEL::Node *,int> m;
8982           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
8983           e->sortSubNodesAbs(coords,isect);
8984           e->decrRef();
8985           for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
8986             (*it2).first->decrRef();
8987         }
8988       if(sz!=0)
8989         {
8990           int idx0(rdi[i]),idx1(rdi[i+1]);
8991           if(idx1-idx0!=1)
8992             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
8993           if(!cells2DToTreat[rd[idx0]])
8994             {
8995               cells2DToTreat[rd[idx0]]=true;
8996               nbOf2DCellsToBeSplit++;
8997             }
8998           // try to reuse at most eventual 'middle' of SEG3
8999           std::vector<int>& mid(middle[i]);
9000           mid.resize(sz+1,-1);
9001           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
9002             {
9003               middleNeedsToBeUsed=true;
9004               const std::vector<int>& candidates(overlapEdge[i]);
9005               std::vector<int> trueCandidates;
9006               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
9007                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
9008                   trueCandidates.push_back(*itc);
9009               int stNode(c[ci[i]+1]),endNode(isect[0]);
9010               for(int j=0;j<sz+1;j++)
9011                 {
9012                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
9013                     {
9014                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
9015                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
9016                         { mid[j]=*itc; break; }
9017                     }
9018                   stNode=endNode;
9019                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
9020                 }
9021             }
9022         }
9023     }
9024   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
9025   if(nbOf2DCellsToBeSplit==0)
9026     return ret.retn();
9027   //
9028   int *retPtr(ret->getPointer());
9029   for(int i=0;i<nCell;i++)
9030     if(cells2DToTreat[i])
9031       *retPtr++=i;
9032   //
9033   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
9034   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
9035   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
9036   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
9037   if(middleNeedsToBeUsed)
9038     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
9039   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
9040   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
9041   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.
9042   setPartOfMySelf(ret->begin(),ret->end(),*modif);
9043   {
9044     bool areNodesMerged; int newNbOfNodes;
9045     if(nbOfNodesCreated!=0)
9046       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
9047   }
9048   return ret.retn();
9049 }
9050
9051 /*!
9052  * 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.
9053  * 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).
9054  * 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
9055  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
9056  * 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
9057  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
9058  *
9059  * 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
9060  * using new instance, idem for coordinates.
9061  *
9062  * 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.
9063  * 
9064  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
9065  *
9066  * \throw If \a this is not coherent.
9067  * \throw If \a this has not spaceDim equal to 2.
9068  * \throw If \a this has not meshDim equal to 2.
9069  * 
9070  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
9071  */
9072 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
9073 {
9074   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
9075   checkCoherency();
9076   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9077     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9078   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9079   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9080   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
9081   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
9082   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
9083   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
9084   const double *coords(_coords->begin());
9085   int *newciptr(newci->getPointer());
9086   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
9087     {
9088       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
9089         ret->pushBackSilent(i);
9090       newciptr[1]=newc->getNumberOfTuples();
9091     }
9092   //
9093   if(ret->empty())
9094     return ret.retn();
9095   if(!appendedCoords->empty())
9096     {
9097       appendedCoords->rearrange(2);
9098       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
9099       //non const part
9100       setCoords(newCoords);
9101     }
9102   //non const part
9103   setConnectivity(newc,newci,true);
9104   return ret.retn();
9105 }
9106
9107 /*!
9108  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
9109  * It builds the descending connectivity of the two meshes, and then using a binary tree
9110  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
9111  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
9112  */
9113 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
9114                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
9115                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
9116                                                    std::vector<double>& addCoo,
9117                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
9118 {
9119   static const int SPACEDIM=2;
9120   // Build desc connectivity
9121   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
9122   desc2=DataArrayInt::New();
9123   descIndx2=DataArrayInt::New();
9124   revDesc2=DataArrayInt::New();
9125   revDescIndx2=DataArrayInt::New();
9126   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9127   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
9128   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
9129   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
9130   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
9131   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
9132   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
9133
9134   // Build BB tree of all edges in the tool mesh (second mesh)
9135   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
9136   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9137   int nDescCell1=m1Desc->getNumberOfCells();
9138   int nDescCell2=m2Desc->getNumberOfCells();
9139   intersectEdge1.resize(nDescCell1);
9140   colinear2.resize(nDescCell2);
9141   subDiv2.resize(nDescCell2);
9142   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
9143
9144   std::vector<int> candidates1(1);
9145   int offset1=m1->getNumberOfNodes();
9146   int offset2=offset1+m2->getNumberOfNodes();
9147   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
9148     {
9149       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
9150       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9151       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
9152         {
9153           std::map<INTERP_KERNEL::Node *,int> map1,map2;
9154           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
9155           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
9156           candidates1[0]=i;
9157           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
9158           // 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
9159           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
9160           std::set<INTERP_KERNEL::Node *> nodes;
9161           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
9162           std::size_t szz(nodes.size());
9163           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
9164           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
9165           for(std::size_t iii=0;iii<szz;iii++,itt++)
9166             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
9167           // end of protection
9168           // Performs egde cutting:
9169           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
9170           delete pol2;
9171           delete pol1;
9172         }
9173       else
9174         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
9175     }
9176   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
9177   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
9178 }
9179
9180 /*!
9181  * This method performs the 2nd step of Partition of 2D mesh.
9182  * This method has 4 inputs :
9183  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
9184  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
9185  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
9186  * 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'
9187  * Nodes end up lying consecutively on a cutted edge.
9188  * \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.
9189  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
9190  * \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.
9191  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
9192  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
9193  */
9194 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9195                                            const std::vector<double>& addCoo,
9196                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
9197 {
9198   int offset1=m1->getNumberOfNodes();
9199   int ncell=m2->getNumberOfCells();
9200   const int *c=m2->getNodalConnectivity()->getConstPointer();
9201   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
9202   const double *coo=m2->getCoords()->getConstPointer();
9203   const double *cooBis=m1->getCoords()->getConstPointer();
9204   int offset2=offset1+m2->getNumberOfNodes();
9205   intersectEdge.resize(ncell);
9206   for(int i=0;i<ncell;i++,cI++)
9207     {
9208       const std::vector<int>& divs=subDiv[i];
9209       int nnode=cI[1]-cI[0]-1;
9210       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
9211       std::map<INTERP_KERNEL::Node *, int> mapp22;
9212       for(int j=0;j<nnode;j++)
9213         {
9214           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
9215           int nnid=c[(*cI)+j+1];
9216           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
9217           mapp22[nn]=nnid+offset1;
9218         }
9219       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
9220       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
9221         ((*it).second.first)->decrRef();
9222       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
9223       std::map<INTERP_KERNEL::Node *,int> mapp3;
9224       for(std::size_t j=0;j<divs.size();j++)
9225         {
9226           int id=divs[j];
9227           INTERP_KERNEL::Node *tmp=0;
9228           if(id<offset1)
9229             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
9230           else if(id<offset2)
9231             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
9232           else
9233             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
9234           addNodes[j]=tmp;
9235           mapp3[tmp]=id;
9236         }
9237       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
9238       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
9239         (*it)->decrRef();
9240       e->decrRef();
9241     }
9242 }
9243
9244 /*!
9245  * 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).
9246  * 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
9247  * with a plane. The result will be put in 'cut3DSuf' out parameter.
9248  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
9249  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
9250  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
9251  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
9252  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
9253  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
9254  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
9255  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
9256  * \param [out] cut3DSuf input/output param.
9257  */
9258 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
9259                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
9260                                                    const int *desc, const int *descIndx, 
9261                                                    std::vector< std::pair<int,int> >& cut3DSurf)
9262 {
9263   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
9264   int nbOf3DSurfCell=(int)cut3DSurf.size();
9265   for(int i=0;i<nbOf3DSurfCell;i++)
9266     {
9267       std::vector<int> res;
9268       int offset=descIndx[i];
9269       int nbOfSeg=descIndx[i+1]-offset;
9270       for(int j=0;j<nbOfSeg;j++)
9271         {
9272           int edgeId=desc[offset+j];
9273           int status=cut3DCurve[edgeId];
9274           if(status!=-2)
9275             {
9276               if(status>-1)
9277                 res.push_back(status);
9278               else
9279                 {
9280                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
9281                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
9282                 }
9283             }
9284         }
9285       switch(res.size())
9286       {
9287         case 2:
9288           {
9289             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9290             break;
9291           }
9292         case 1:
9293         case 0:
9294           {
9295             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
9296             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
9297             if(res.size()==2)
9298               {
9299                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9300               }
9301             else
9302               {
9303                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
9304               }
9305             break;
9306           }
9307         default:
9308           {// case when plane is on a multi colinear edge of a polyhedron
9309             if((int)res.size()==2*nbOfSeg)
9310               {
9311                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
9312               }
9313             else
9314               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
9315           }
9316       }
9317     }
9318 }
9319
9320 /*!
9321  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
9322  * 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).
9323  * 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
9324  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
9325  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
9326  * \param desc is the descending connectivity 3D->3DSurf
9327  * \param descIndx is the descending connectivity index 3D->3DSurf
9328  */
9329 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
9330                                                   const int *desc, const int *descIndx,
9331                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
9332 {
9333   checkFullyDefined();
9334   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9335     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
9336   const int *nodal3D=_nodal_connec->getConstPointer();
9337   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
9338   int nbOfCells=getNumberOfCells();
9339   for(int i=0;i<nbOfCells;i++)
9340     {
9341       std::map<int, std::set<int> > m;
9342       int offset=descIndx[i];
9343       int nbOfFaces=descIndx[i+1]-offset;
9344       int start=-1;
9345       int end=-1;
9346       for(int j=0;j<nbOfFaces;j++)
9347         {
9348           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
9349           if(p.first!=-1 && p.second!=-1)
9350             {
9351               if(p.first!=-2)
9352                 {
9353                   start=p.first; end=p.second;
9354                   m[p.first].insert(p.second);
9355                   m[p.second].insert(p.first);
9356                 }
9357               else
9358                 {
9359                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
9360                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
9361                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
9362                   INTERP_KERNEL::NormalizedCellType cmsId;
9363                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
9364                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
9365                   for(unsigned k=0;k<nbOfNodesSon;k++)
9366                     {
9367                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
9368                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
9369                     }
9370                 }
9371             }
9372         }
9373       if(m.empty())
9374         continue;
9375       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
9376       int prev=end;
9377       while(end!=start)
9378         {
9379           std::map<int, std::set<int> >::const_iterator it=m.find(start);
9380           const std::set<int>& s=(*it).second;
9381           std::set<int> s2; s2.insert(prev);
9382           std::set<int> s3;
9383           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
9384           if(s3.size()==1)
9385             {
9386               int val=*s3.begin();
9387               conn.push_back(start);
9388               prev=start;
9389               start=val;
9390             }
9391           else
9392             start=end;
9393         }
9394       conn.push_back(end);
9395       if(conn.size()>3)
9396         {
9397           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
9398           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
9399           cellIds->pushBackSilent(i);
9400         }
9401     }
9402 }
9403
9404 /*!
9405  * 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
9406  * 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
9407  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
9408  * 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
9409  * 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.
9410  * 
9411  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
9412  */
9413 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
9414 {
9415   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
9416   if(sz>=4)
9417     {
9418       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
9419       if(cm.getDimension()==2)
9420         {
9421           const int *node=nodalConnBg+1;
9422           int startNode=*node++;
9423           double refX=coords[2*startNode];
9424           for(;node!=nodalConnEnd;node++)
9425             {
9426               if(coords[2*(*node)]<refX)
9427                 {
9428                   startNode=*node;
9429                   refX=coords[2*startNode];
9430                 }
9431             }
9432           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
9433           refX=1e300;
9434           double tmp1;
9435           double tmp2[2];
9436           double angle0=-M_PI/2;
9437           //
9438           int nextNode=-1;
9439           int prevNode=-1;
9440           double resRef;
9441           double angleNext=0.;
9442           while(nextNode!=startNode)
9443             {
9444               nextNode=-1;
9445               resRef=1e300;
9446               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
9447                 {
9448                   if(*node!=tmpOut.back() && *node!=prevNode)
9449                     {
9450                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
9451                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
9452                       double res;
9453                       if(angleM<=angle0)
9454                         res=angle0-angleM;
9455                       else
9456                         res=angle0-angleM+2.*M_PI;
9457                       if(res<resRef)
9458                         {
9459                           nextNode=*node;
9460                           resRef=res;
9461                           angleNext=angleM;
9462                         }
9463                     }
9464                 }
9465               if(nextNode!=startNode)
9466                 {
9467                   angle0=angleNext-M_PI;
9468                   if(angle0<-M_PI)
9469                     angle0+=2*M_PI;
9470                   prevNode=tmpOut.back();
9471                   tmpOut.push_back(nextNode);
9472                 }
9473             }
9474           std::vector<int> tmp3(2*(sz-1));
9475           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
9476           std::copy(nodalConnBg+1,nodalConnEnd,it);
9477           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
9478             {
9479               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9480               return false;
9481             }
9482           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
9483             {
9484               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9485               return false;
9486             }
9487           else
9488             {
9489               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
9490               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
9491               return true;
9492             }
9493         }
9494       else
9495         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9496     }
9497   else
9498     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9499 }
9500
9501 /*!
9502  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
9503  * 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.
9504  * 
9505  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
9506  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
9507  * \param [in,out] arr array in which the remove operation will be done.
9508  * \param [in,out] arrIndx array in the remove operation will modify
9509  * \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])
9510  * \return true if \b arr and \b arrIndx have been modified, false if not.
9511  */
9512 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
9513 {
9514   if(!arrIndx || !arr)
9515     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
9516   if(offsetForRemoval<0)
9517     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
9518   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
9519   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
9520   int *arrIPtr=arrIndx->getPointer();
9521   *arrIPtr++=0;
9522   int previousArrI=0;
9523   const int *arrPtr=arr->getConstPointer();
9524   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
9525   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
9526     {
9527       if(*arrIPtr-previousArrI>offsetForRemoval)
9528         {
9529           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
9530             {
9531               if(s.find(*work)==s.end())
9532                 arrOut.push_back(*work);
9533             }
9534         }
9535       previousArrI=*arrIPtr;
9536       *arrIPtr=(int)arrOut.size();
9537     }
9538   if(arr->getNumberOfTuples()==(int)arrOut.size())
9539     return false;
9540   arr->alloc((int)arrOut.size(),1);
9541   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
9542   return true;
9543 }
9544
9545 /*!
9546  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9547  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
9548  * The selection of extraction is done standardly in new2old format.
9549  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9550  *
9551  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9552  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9553  * \param [in] arrIn arr origin array from which the extraction will be done.
9554  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9555  * \param [out] arrOut the resulting array
9556  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9557  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
9558  */
9559 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9560                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
9561 {
9562   if(!arrIn || !arrIndxIn)
9563     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
9564   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9565   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9566     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
9567   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
9568   const int *arrInPtr=arrIn->getConstPointer();
9569   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9570   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9571   if(nbOfGrps<0)
9572     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9573   int maxSizeOfArr=arrIn->getNumberOfTuples();
9574   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9575   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9576   arrIo->alloc((int)(sz+1),1);
9577   const int *idsIt=idsOfSelectBg;
9578   int *work=arrIo->getPointer();
9579   *work++=0;
9580   int lgth=0;
9581   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
9582     {
9583       if(*idsIt>=0 && *idsIt<nbOfGrps)
9584         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
9585       else
9586         {
9587           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9588           throw INTERP_KERNEL::Exception(oss.str().c_str());
9589         }
9590       if(lgth>=work[-1])
9591         *work=lgth;
9592       else
9593         {
9594           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
9595           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
9596           throw INTERP_KERNEL::Exception(oss.str().c_str());
9597         }
9598     }
9599   arro->alloc(lgth,1);
9600   work=arro->getPointer();
9601   idsIt=idsOfSelectBg;
9602   for(std::size_t i=0;i<sz;i++,idsIt++)
9603     {
9604       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
9605         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
9606       else
9607         {
9608           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
9609           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9610           throw INTERP_KERNEL::Exception(oss.str().c_str());
9611         }
9612     }
9613   arrOut=arro.retn();
9614   arrIndexOut=arrIo.retn();
9615 }
9616
9617 /*!
9618  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9619  * 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 ).
9620  * The selection of extraction is done standardly in new2old format.
9621  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9622  *
9623  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9624  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9625  * \param [in] arrIn arr origin array from which the extraction will be done.
9626  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9627  * \param [out] arrOut the resulting array
9628  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9629  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
9630  */
9631 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9632                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
9633 {
9634   if(!arrIn || !arrIndxIn)
9635     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
9636   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9637   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9638     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
9639   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
9640   const int *arrInPtr=arrIn->getConstPointer();
9641   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9642   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9643   if(nbOfGrps<0)
9644     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9645   int maxSizeOfArr=arrIn->getNumberOfTuples();
9646   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9647   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9648   arrIo->alloc((int)(sz+1),1);
9649   int idsIt=idsOfSelectStart;
9650   int *work=arrIo->getPointer();
9651   *work++=0;
9652   int lgth=0;
9653   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
9654     {
9655       if(idsIt>=0 && idsIt<nbOfGrps)
9656         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
9657       else
9658         {
9659           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9660           throw INTERP_KERNEL::Exception(oss.str().c_str());
9661         }
9662       if(lgth>=work[-1])
9663         *work=lgth;
9664       else
9665         {
9666           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
9667           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
9668           throw INTERP_KERNEL::Exception(oss.str().c_str());
9669         }
9670     }
9671   arro->alloc(lgth,1);
9672   work=arro->getPointer();
9673   idsIt=idsOfSelectStart;
9674   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
9675     {
9676       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
9677         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
9678       else
9679         {
9680           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
9681           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9682           throw INTERP_KERNEL::Exception(oss.str().c_str());
9683         }
9684     }
9685   arrOut=arro.retn();
9686   arrIndexOut=arrIo.retn();
9687 }
9688
9689 /*!
9690  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9691  * 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
9692  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9693  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9694  *
9695  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9696  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9697  * \param [in] arrIn arr origin array from which the extraction will be done.
9698  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9699  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
9700  * \param [in] srcArrIndex index array of \b srcArr
9701  * \param [out] arrOut the resulting array
9702  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9703  * 
9704  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9705  */
9706 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9707                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9708                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
9709 {
9710   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9711     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9712   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9713   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9714   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9715   std::vector<bool> v(nbOfTuples,true);
9716   int offset=0;
9717   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9718   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9719   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9720     {
9721       if(*it>=0 && *it<nbOfTuples)
9722         {
9723           v[*it]=false;
9724           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9725         }
9726       else
9727         {
9728           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9729           throw INTERP_KERNEL::Exception(oss.str().c_str());
9730         }
9731     }
9732   srcArrIndexPtr=srcArrIndex->getConstPointer();
9733   arrIo->alloc(nbOfTuples+1,1);
9734   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9735   const int *arrInPtr=arrIn->getConstPointer();
9736   const int *srcArrPtr=srcArr->getConstPointer();
9737   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9738   int *arroPtr=arro->getPointer();
9739   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9740     {
9741       if(v[ii])
9742         {
9743           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9744           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9745         }
9746       else
9747         {
9748           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9749           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9750           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9751         }
9752     }
9753   arrOut=arro.retn();
9754   arrIndexOut=arrIo.retn();
9755 }
9756
9757 /*!
9758  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9759  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9760  *
9761  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9762  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9763  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9764  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9765  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
9766  * \param [in] srcArrIndex index array of \b srcArr
9767  * 
9768  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9769  */
9770 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9771                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
9772 {
9773   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9774     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9775   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9776   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9777   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9778   int *arrInOutPtr=arrInOut->getPointer();
9779   const int *srcArrPtr=srcArr->getConstPointer();
9780   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9781     {
9782       if(*it>=0 && *it<nbOfTuples)
9783         {
9784           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9785             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9786           else
9787             {
9788               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] !";
9789               throw INTERP_KERNEL::Exception(oss.str().c_str());
9790             }
9791         }
9792       else
9793         {
9794           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9795           throw INTERP_KERNEL::Exception(oss.str().c_str());
9796         }
9797     }
9798 }
9799
9800 /*!
9801  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9802  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9803  * 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]].
9804  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9805  * A negative value in \b arrIn means that it is ignored.
9806  * 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.
9807  * 
9808  * \param [in] arrIn arr origin array from which the extraction will be done.
9809  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9810  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9811  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9812  */
9813 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9814 {
9815   int seed=0,nbOfDepthPeelingPerformed=0;
9816   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9817 }
9818
9819 /*!
9820  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9821  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9822  * 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]].
9823  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9824  * A negative value in \b arrIn means that it is ignored.
9825  * 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.
9826  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9827  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9828  * \param [in] arrIn arr origin array from which the extraction will be done.
9829  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9830  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9831  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9832  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9833  * \sa MEDCouplingUMesh::partitionBySpreadZone
9834  */
9835 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9836 {
9837   nbOfDepthPeelingPerformed=0;
9838   if(!arrIndxIn)
9839     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9840   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9841   if(nbOfTuples<=0)
9842     {
9843       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9844       return ret;
9845     }
9846   //
9847   std::vector<bool> fetched(nbOfTuples,false);
9848   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9849 }
9850
9851 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9852 {
9853   nbOfDepthPeelingPerformed=0;
9854   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9855     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9856   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9857   std::vector<bool> fetched2(nbOfTuples,false);
9858   int i=0;
9859   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9860     {
9861       if(*seedElt>=0 && *seedElt<nbOfTuples)
9862         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9863       else
9864         { 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()); }
9865     }
9866   const int *arrInPtr=arrIn->getConstPointer();
9867   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9868   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9869   std::vector<int> idsToFetch1(seedBg,seedEnd);
9870   std::vector<int> idsToFetch2;
9871   std::vector<int> *idsToFetch=&idsToFetch1;
9872   std::vector<int> *idsToFetchOther=&idsToFetch2;
9873   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9874     {
9875       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9876         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9877           if(!fetched[*it2])
9878             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9879       std::swap(idsToFetch,idsToFetchOther);
9880       idsToFetchOther->clear();
9881       nbOfDepthPeelingPerformed++;
9882     }
9883   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9884   i=0;
9885   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9886   int *retPtr=ret->getPointer();
9887   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9888     if(*it)
9889       *retPtr++=i;
9890   return ret.retn();
9891 }
9892
9893 /*!
9894  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9895  * 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
9896  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9897  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9898  *
9899  * \param [in] start begin of set of ids of the input extraction (included)
9900  * \param [in] end end of set of ids of the input extraction (excluded)
9901  * \param [in] step step of the set of ids in range mode.
9902  * \param [in] arrIn arr origin array from which the extraction will be done.
9903  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9904  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9905  * \param [in] srcArrIndex index array of \b srcArr
9906  * \param [out] arrOut the resulting array
9907  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9908  * 
9909  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9910  */
9911 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9912                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9913                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
9914 {
9915   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9916     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9917   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9918   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9919   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9920   int offset=0;
9921   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9922   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9923   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9924   int it=start;
9925   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9926     {
9927       if(it>=0 && it<nbOfTuples)
9928         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9929       else
9930         {
9931           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9932           throw INTERP_KERNEL::Exception(oss.str().c_str());
9933         }
9934     }
9935   srcArrIndexPtr=srcArrIndex->getConstPointer();
9936   arrIo->alloc(nbOfTuples+1,1);
9937   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9938   const int *arrInPtr=arrIn->getConstPointer();
9939   const int *srcArrPtr=srcArr->getConstPointer();
9940   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9941   int *arroPtr=arro->getPointer();
9942   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9943     {
9944       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9945       if(pos<0)
9946         {
9947           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9948           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9949         }
9950       else
9951         {
9952           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9953           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9954         }
9955     }
9956   arrOut=arro.retn();
9957   arrIndexOut=arrIo.retn();
9958 }
9959
9960 /*!
9961  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9962  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9963  *
9964  * \param [in] start begin of set of ids of the input extraction (included)
9965  * \param [in] end end of set of ids of the input extraction (excluded)
9966  * \param [in] step step of the set of ids in range mode.
9967  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9968  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9969  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9970  * \param [in] srcArrIndex index array of \b srcArr
9971  * 
9972  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9973  */
9974 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9975                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
9976 {
9977   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9978     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9979   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9980   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9981   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9982   int *arrInOutPtr=arrInOut->getPointer();
9983   const int *srcArrPtr=srcArr->getConstPointer();
9984   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9985   int it=start;
9986   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9987     {
9988       if(it>=0 && it<nbOfTuples)
9989         {
9990           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9991             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9992           else
9993             {
9994               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9995               throw INTERP_KERNEL::Exception(oss.str().c_str());
9996             }
9997         }
9998       else
9999         {
10000           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
10001           throw INTERP_KERNEL::Exception(oss.str().c_str());
10002         }
10003     }
10004 }
10005
10006 /*!
10007  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
10008  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
10009  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
10010  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
10011  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
10012  * 
10013  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
10014  */
10015 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
10016 {
10017   checkFullyDefined();
10018   int mdim=getMeshDimension();
10019   int spaceDim=getSpaceDimension();
10020   if(mdim!=spaceDim)
10021     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
10022   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
10023   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
10024   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
10025   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
10026   ret->setCoords(getCoords());
10027   ret->allocateCells((int)partition.size());
10028   //
10029   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
10030     {
10031       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
10032       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
10033       switch(mdim)
10034       {
10035         case 2:
10036           cell=tmp->buildUnionOf2DMesh();
10037           break;
10038         case 3:
10039           cell=tmp->buildUnionOf3DMesh();
10040           break;
10041         default:
10042           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
10043       }
10044
10045       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
10046     }
10047   //
10048   ret->finishInsertingCells();
10049   return ret.retn();
10050 }
10051
10052 /*!
10053  * This method partitions \b this into contiguous zone.
10054  * This method only needs a well defined connectivity. Coordinates are not considered here.
10055  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
10056  */
10057 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
10058 {
10059   int nbOfCellsCur=getNumberOfCells();
10060   std::vector<DataArrayInt *> ret;
10061   if(nbOfCellsCur<=0)
10062     return ret;
10063   DataArrayInt *neigh=0,*neighI=0;
10064   computeNeighborsOfCells(neigh,neighI);
10065   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
10066   std::vector<bool> fetchedCells(nbOfCellsCur,false);
10067   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
10068   int seed=0;
10069   while(seed<nbOfCellsCur)
10070     {
10071       int nbOfPeelPerformed=0;
10072       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
10073       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
10074     }
10075   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
10076     ret.push_back((*it).retn());
10077   return ret;
10078 }
10079
10080 /*!
10081  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
10082  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
10083  *
10084  * \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.
10085  * \return a newly allocated DataArrayInt to be managed by the caller.
10086  * \throw In case of \a code has not the right format (typically of size 3*n)
10087  */
10088 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
10089 {
10090   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
10091   std::size_t nb=code.size()/3;
10092   if(code.size()%3!=0)
10093     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
10094   ret->alloc((int)nb,2);
10095   int *retPtr=ret->getPointer();
10096   for(std::size_t i=0;i<nb;i++,retPtr+=2)
10097     {
10098       retPtr[0]=code[3*i+2];
10099       retPtr[1]=code[3*i+2]+code[3*i+1];
10100     }
10101   return ret.retn();
10102 }
10103
10104 /*!
10105  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
10106  * All cells in \a this are expected to be linear 3D cells.
10107  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
10108  * It leads to an increase to number of cells.
10109  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
10110  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
10111  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
10112  *
10113  * \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.
10114  *                      For all other cells, the splitting policy will be ignored.
10115  * \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. 
10116  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
10117  *          an id of old cell producing it. The caller is to delete this array using
10118  *         decrRef() as it is no more needed.
10119  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
10120  *
10121  * \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
10122  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
10123  * 
10124  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
10125  * \throw If \a this is not fully constituted with linear 3D cells.
10126  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
10127  */
10128 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
10129 {
10130   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
10131   checkConnectivityFullyDefined();
10132   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10133     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
10134   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
10135   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
10136   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
10137   int *retPt(ret->getPointer());
10138   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
10139   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
10140   const int *oldc(_nodal_connec->begin());
10141   const int *oldci(_nodal_connec_index->begin());
10142   const double *coords(_coords->begin());
10143   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
10144     {
10145       std::vector<int> a; std::vector<double> b;
10146       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
10147       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
10148       const int *aa(&a[0]);
10149       if(!b.empty())
10150         {
10151           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
10152             if(*it<0)
10153               *it=(-(*(it))-1+nbNodes);
10154           addPts->insertAtTheEnd(b.begin(),b.end());
10155           nbNodes+=(int)b.size()/3;
10156         }
10157       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
10158         newConn->insertAtTheEnd(aa,aa+4);
10159     }
10160   if(!addPts->empty())
10161     {
10162       addPts->rearrange(3);
10163       nbOfAdditionalPoints=addPts->getNumberOfTuples();
10164       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
10165       ret0->setCoords(addPts);
10166     }
10167   else
10168     {
10169       nbOfAdditionalPoints=0;
10170       ret0->setCoords(getCoords());
10171     }
10172   ret0->setNodalConnectivity(newConn);
10173   //
10174   ret->computeOffsets2();
10175   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
10176   return ret0.retn();
10177 }
10178
10179 /*!
10180  * 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). 
10181  *
10182  * \sa MEDCouplingUMesh::split2DCells
10183  */
10184 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
10185 {
10186   checkConnectivityFullyDefined();
10187   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
10188   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10189   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10190   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10191   int prevPosOfCi(ciPtr[0]);
10192   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10193     {
10194       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
10195       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
10196       for(int j=0;j<sz;j++)
10197         {
10198           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
10199           for(int k=0;k<sz2;k++)
10200             *cPtr++=subPtr[offset2+k];
10201           if(j!=sz-1)
10202             *cPtr++=oldConn[prevPosOfCi+j+2];
10203           deltaSz+=sz2;
10204         }
10205       prevPosOfCi=ciPtr[1];
10206       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10207     }
10208   if(c->end()!=cPtr)
10209     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
10210   _nodal_connec->decrRef();
10211   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
10212 }
10213
10214 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
10215 {
10216   if(id!=-1)
10217     return id;
10218   else
10219     {
10220       int ret(nodesCnter++);
10221       double newPt[2];
10222       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
10223       addCoo.insertAtTheEnd(newPt,newPt+2);
10224       return ret;
10225     }
10226 }
10227
10228 /// @cond INTERNAL
10229
10230 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)
10231 {
10232   int tmp[3];
10233   int trueStart(start>=0?start:nbOfEdges+start);
10234   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
10235   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
10236   if(linOrArc)
10237     {
10238       if(stp-start>1)
10239         {
10240           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10241           InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
10242           middles.push_back(tmp3+offset);
10243         }
10244       else
10245         middles.push_back(connBg[trueStart+nbOfEdges]);
10246     }
10247 }
10248
10249 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)
10250 {
10251   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
10252   newConnOfCell->pushBackSilent(tmpEnd);
10253   if(linOrArc)
10254     {
10255       if(stp-start>1)
10256         {
10257           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10258           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
10259           middles.push_back(tmp3+offset);
10260         }
10261       else
10262         middles.push_back(connBg[start+nbOfEdges]);
10263     }
10264 }
10265
10266 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)
10267 {
10268   if(linOrArc)
10269     {
10270       if(stp-start>1)
10271         {
10272           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
10273           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10274           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
10275           middles.push_back(tmp3+offset);
10276         }
10277       else
10278         middles.push_back(connBg[start+nbOfEdges]);
10279     }
10280 }
10281
10282 /// @cond INTERNAL
10283
10284 /*!
10285  * 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 ) .
10286  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
10287  */
10288 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
10289 {
10290   std::size_t sz(std::distance(connBg,connEnd));
10291   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
10292     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
10293   sz--;
10294   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
10295   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
10296   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
10297   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
10298   INTERP_KERNEL::NormalizedCellType typeOfSon;
10299   std::vector<int> middles;
10300   bool ret(false);
10301   for(;nbOfHit<nbs;nbOfTurn++)
10302     {
10303       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
10304       std::map<INTERP_KERNEL::Node *,int> m;
10305       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
10306       posEndElt++;
10307       nbOfHit++;
10308       unsigned endI(nbs-nbOfHit);
10309       for(unsigned i=0;i<endI;i++)
10310         {
10311           cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
10312           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
10313           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
10314           bool isColinear(eint->areColinears());
10315           if(isColinear)
10316             {
10317               nbOfHit++;
10318               posEndElt++;
10319               ret=true;
10320             }
10321           delete eint;
10322           eCand->decrRef();
10323           if(!isColinear)
10324             {
10325               if(nbOfTurn==0)
10326                 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
10327                   unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
10328                   for(unsigned ii=0;ii<endII;ii++)
10329                     {
10330                       cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
10331                       eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
10332                       eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
10333                       isColinear=eint->areColinears();
10334                       if(isColinear)
10335                         {
10336                           nbOfHit++;
10337                           posBaseElt--;
10338                           ret=true;
10339                         }
10340                       delete eint;
10341                       eCand->decrRef();
10342                       if(!isColinear)
10343                         break;
10344                     }
10345                 }
10346               break;
10347             }
10348         }
10349       //push [posBaseElt,posEndElt) in newConnOfCell using e
10350       if(nbOfTurn==0)
10351         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10352       else if(nbOfHit!=nbs)
10353         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10354       else
10355         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10356       posBaseElt=posEndElt;
10357       for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it=m.begin();it!=m.end();it++)
10358         (*it).first->decrRef();
10359       e->decrRef();
10360     }
10361   if(!middles.empty())
10362     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
10363   return ret;
10364 }
10365
10366 /*!
10367  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
10368  *
10369  * \return  int - the number of new nodes created.
10370  * \sa MEDCouplingUMesh::split2DCells
10371  */
10372 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
10373 {
10374   checkCoherency();
10375   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
10376   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10377   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
10378   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10379   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
10380   const double *oldCoordsPtr(getCoords()->begin());
10381   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10382   int prevPosOfCi(ciPtr[0]);
10383   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10384     {
10385       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
10386       for(int j=0;j<sz;j++)
10387         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
10388       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
10389       for(int j=0;j<sz;j++)//loop over subedges of oldConn
10390         {
10391           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
10392           if(sz2==0)
10393             {
10394               if(j<sz-1)
10395                 cPtr[1]=oldConn[prevPosOfCi+2+j];
10396               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
10397               continue;
10398             }
10399           std::vector<INTERP_KERNEL::Node *> ns(3);
10400           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
10401           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
10402           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
10403           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
10404           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
10405             {
10406               cPtr[1]=subPtr[offset2+k];
10407               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
10408             }
10409           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
10410           if(j!=sz-1)
10411             { cPtr[1]=tmpEnd; }
10412           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
10413         }
10414       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
10415       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10416     }
10417   if(c->end()!=cPtr)
10418     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
10419   _nodal_connec->decrRef();
10420   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
10421   addCoo->rearrange(2);
10422   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
10423   setCoords(coo);
10424   return addCoo->getNumberOfTuples();
10425 }
10426
10427 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
10428     _own_cell(true),_cell_id(-1),_nb_cell(0)
10429 {
10430   if(mesh)
10431     {
10432       mesh->incrRef();
10433       _nb_cell=mesh->getNumberOfCells();
10434     }
10435 }
10436
10437 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
10438 {
10439   if(_mesh)
10440     _mesh->decrRef();
10441   if(_own_cell)
10442     delete _cell;
10443 }
10444
10445 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
10446     _own_cell(false),_cell_id(bg-1),
10447     _nb_cell(end)
10448 {
10449   if(mesh)
10450     mesh->incrRef();
10451 }
10452
10453 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
10454 {
10455   _cell_id++;
10456   if(_cell_id<_nb_cell)
10457     {
10458       _cell->next();
10459       return _cell;
10460     }
10461   else
10462     return 0;
10463 }
10464
10465 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
10466 {
10467   if(_mesh)
10468     _mesh->incrRef();
10469 }
10470
10471 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
10472 {
10473   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
10474 }
10475
10476 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
10477 {
10478   if(_mesh)
10479     _mesh->decrRef();
10480 }
10481
10482 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
10483     _itc(itc),
10484     _bg(bg),_end(end)
10485 {
10486   if(_mesh)
10487     _mesh->incrRef();
10488 }
10489
10490 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
10491 {
10492   if(_mesh)
10493     _mesh->decrRef();
10494 }
10495
10496 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
10497 {
10498   return _type;
10499 }
10500
10501 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
10502 {
10503   return _end-_bg;
10504 }
10505
10506 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
10507 {
10508   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
10509 }
10510
10511 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
10512 {
10513   if(mesh)
10514     {
10515       mesh->incrRef();
10516       _nb_cell=mesh->getNumberOfCells();
10517     }
10518 }
10519
10520 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
10521 {
10522   if(_mesh)
10523     _mesh->decrRef();
10524   delete _cell;
10525 }
10526
10527 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
10528 {
10529   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
10530   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
10531   if(_cell_id<_nb_cell)
10532     {
10533       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
10534       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
10535       int startId=_cell_id;
10536       _cell_id+=nbOfElems;
10537       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
10538     }
10539   else
10540     return 0;
10541 }
10542
10543 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
10544 {
10545   if(mesh)
10546     {
10547       _conn=mesh->getNodalConnectivity()->getPointer();
10548       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
10549     }
10550 }
10551
10552 void MEDCouplingUMeshCell::next()
10553 {
10554   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10555     {
10556       _conn+=_conn_lgth;
10557       _conn_indx++;
10558     }
10559   _conn_lgth=_conn_indx[1]-_conn_indx[0];
10560 }
10561
10562 std::string MEDCouplingUMeshCell::repr() const
10563 {
10564   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10565     {
10566       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
10567       oss << " : ";
10568       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
10569       return oss.str();
10570     }
10571   else
10572     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
10573 }
10574
10575 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
10576 {
10577   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10578     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
10579   else
10580     return INTERP_KERNEL::NORM_ERROR;
10581 }
10582
10583 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
10584 {
10585   lgth=_conn_lgth;
10586   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10587     return _conn;
10588   else
10589     return 0;
10590 }