Salome HOME
Unwarnigization campaign. First auto indentation with Eclipse on MEDCouplingUMesh.
[modules/med.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
42
43 #include <sstream>
44 #include <fstream>
45 #include <numeric>
46 #include <cstring>
47 #include <limits>
48 #include <list>
49
50 using namespace ParaMEDMEM;
51
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53
54 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
55
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 {
58   return new MEDCouplingUMesh;
59 }
60
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
62 {
63   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64   ret->setName(meshName);
65   ret->setMeshDimension(meshDim);
66   return ret;
67 }
68
69 /*!
70  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71  * between \a this and the new mesh.
72  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73  *          delete this mesh using decrRef() as it is no more needed. 
74  */
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
76 {
77   return clone(true);
78 }
79
80 /*!
81  * Returns a new MEDCouplingMesh which is a copy of \a this one.
82  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83  * this mesh are shared by the new mesh.
84  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85  *          delete this mesh using decrRef() as it is no more needed. 
86  */
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
88 {
89   return new MEDCouplingUMesh(*this,recDeepCpy);
90 }
91
92 /*!
93  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94  * The coordinates are shared between \a this and the returned instance.
95  * 
96  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97  * \sa MEDCouplingUMesh::deepCpy
98  */
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
100 {
101   checkConnectivityFullyDefined();
102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104   ret->setConnectivity(c,ci);
105   return ret.retn();
106 }
107
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
109 {
110   if(!other)
111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
113   if(!otherC)
114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
117 }
118
119 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
120 {
121   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
122   return ret;
123 }
124
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildren() const
126 {
127   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildren());
128   if(_nodal_connec)
129     ret.push_back(_nodal_connec);
130   if(_nodal_connec_index)
131     ret.push_back(_nodal_connec_index);
132   return ret;
133 }
134
135 void MEDCouplingUMesh::updateTime() const
136 {
137   MEDCouplingPointSet::updateTime();
138   if(_nodal_connec)
139     {
140       updateTimeWith(*_nodal_connec);
141     }
142   if(_nodal_connec_index)
143     {
144       updateTimeWith(*_nodal_connec_index);
145     }
146 }
147
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
149 {
150 }
151
152 /*!
153  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154  * then \a this mesh is most probably is writable, exchangeable and available for most
155  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156  * this method to check that all is in order with \a this mesh.
157  *  \throw If the mesh dimension is not set.
158  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
159  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160  *  \throw If the connectivity data array has more than one component.
161  *  \throw If the connectivity data array has a named component.
162  *  \throw If the connectivity index data array has more than one component.
163  *  \throw If the connectivity index data array has a named component.
164  */
165 void MEDCouplingUMesh::checkCoherency() const
166 {
167   if(_mesh_dim<-1)
168     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
169   if(_mesh_dim!=-1)
170     MEDCouplingPointSet::checkCoherency();
171   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
172     {
173       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
174         {
175           std::ostringstream message;
176           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177           throw INTERP_KERNEL::Exception(message.str().c_str());
178         }
179     }
180   if(_nodal_connec)
181     {
182       if(_nodal_connec->getNumberOfComponents()!=1)
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184       if(_nodal_connec->getInfoOnComponent(0)!="")
185         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
186     }
187   else
188     if(_mesh_dim!=-1)
189       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190   if(_nodal_connec_index)
191     {
192       if(_nodal_connec_index->getNumberOfComponents()!=1)
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194       if(_nodal_connec_index->getInfoOnComponent(0)!="")
195         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
196     }
197   else
198     if(_mesh_dim!=-1)
199       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
200 }
201
202 /*!
203  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204  * then \a this mesh is most probably is writable, exchangeable and available for all
205  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206  * method thoroughly checks the nodal connectivity.
207  *  \param [in] eps - a not used parameter.
208  *  \throw If the mesh dimension is not set.
209  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
210  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211  *  \throw If the connectivity data array has more than one component.
212  *  \throw If the connectivity data array has a named component.
213  *  \throw If the connectivity index data array has more than one component.
214  *  \throw If the connectivity index data array has a named component.
215  *  \throw If number of nodes defining an element does not correspond to the type of element.
216  *  \throw If the nodal connectivity includes an invalid node id.
217  */
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
219 {
220   checkCoherency();
221   if(_mesh_dim==-1)
222     return ;
223   int meshDim=getMeshDimension();
224   int nbOfNodes=getNumberOfNodes();
225   int nbOfCells=getNumberOfCells();
226   const int *ptr=_nodal_connec->getConstPointer();
227   const int *ptrI=_nodal_connec_index->getConstPointer();
228   for(int i=0;i<nbOfCells;i++)
229     {
230       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231       if((int)cm.getDimension()!=meshDim)
232         {
233           std::ostringstream oss;
234           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235           throw INTERP_KERNEL::Exception(oss.str().c_str());
236         }
237       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
238       if(!cm.isDynamic())
239         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
240           {
241             std::ostringstream oss;
242             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
243             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244             throw INTERP_KERNEL::Exception(oss.str().c_str());
245           }
246       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
247         {
248           int nodeId=*w;
249           if(nodeId>=0)
250             {
251               if(nodeId>=nbOfNodes)
252                 {
253                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
254                   throw INTERP_KERNEL::Exception(oss.str().c_str());
255                 }
256             }
257           else if(nodeId<-1)
258             {
259               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
260               throw INTERP_KERNEL::Exception(oss.str().c_str());
261             }
262           else
263             {
264               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
265                 {
266                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
267                   throw INTERP_KERNEL::Exception(oss.str().c_str());
268                 }
269             }
270         }
271     }
272 }
273
274
275 /*!
276  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
277  * then \a this mesh is most probably is writable, exchangeable and available for all
278  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
279  *  \param [in] eps - a not used parameter.
280  *  \throw If the mesh dimension is not set.
281  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
282  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
283  *  \throw If the connectivity data array has more than one component.
284  *  \throw If the connectivity data array has a named component.
285  *  \throw If the connectivity index data array has more than one component.
286  *  \throw If the connectivity index data array has a named component.
287  *  \throw If number of nodes defining an element does not correspond to the type of element.
288  *  \throw If the nodal connectivity includes an invalid node id.
289  */
290 void MEDCouplingUMesh::checkCoherency2(double eps) const
291 {
292   checkCoherency1(eps);
293 }
294
295 /*!
296  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
297  * elements contained in the mesh. For more info on the mesh dimension see
298  * \ref MEDCouplingUMeshPage.
299  *  \param [in] meshDim - a new mesh dimension.
300  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
301  */
302 void MEDCouplingUMesh::setMeshDimension(int meshDim)
303 {
304   if(meshDim<-1 || meshDim>3)
305     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
306   _mesh_dim=meshDim;
307   declareAsNew();
308 }
309
310 /*!
311  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
312  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
313  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
314  *
315  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
316  *
317  *  \if ENABLE_EXAMPLES
318  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
319  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
320  *  \endif
321  */
322 void MEDCouplingUMesh::allocateCells(int nbOfCells)
323 {
324   if(nbOfCells<0)
325     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
326   if(_nodal_connec_index)
327     {
328       _nodal_connec_index->decrRef();
329     }
330   if(_nodal_connec)
331     {
332       _nodal_connec->decrRef();
333     }
334   _nodal_connec_index=DataArrayInt::New();
335   _nodal_connec_index->reserve(nbOfCells+1);
336   _nodal_connec_index->pushBackSilent(0);
337   _nodal_connec=DataArrayInt::New();
338   _nodal_connec->reserve(2*nbOfCells);
339   _types.clear();
340   declareAsNew();
341 }
342
343 /*!
344  * Appends a cell to the connectivity array. For deeper understanding what is
345  * happening see \ref MEDCouplingUMeshNodalConnectivity.
346  *  \param [in] type - type of cell to add.
347  *  \param [in] size - number of nodes constituting this cell.
348  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
349  * 
350  *  \if ENABLE_EXAMPLES
351  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
352  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
353  *  \endif
354  */
355 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
356 {
357   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
358   if(_nodal_connec_index==0)
359     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
360   if((int)cm.getDimension()==_mesh_dim)
361     {
362       if(!cm.isDynamic())
363         if(size!=(int)cm.getNumberOfNodes())
364           {
365             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
366             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
367             throw INTERP_KERNEL::Exception(oss.str().c_str());
368           }
369       int idx=_nodal_connec_index->back();
370       int val=idx+size+1;
371       _nodal_connec_index->pushBackSilent(val);
372       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
373       _types.insert(type);
374     }
375   else
376     {
377       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
378       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
379       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
380       throw INTERP_KERNEL::Exception(oss.str().c_str());
381     }
382 }
383
384 /*!
385  * Compacts data arrays to release unused memory. This method is to be called after
386  * finishing cell insertion using \a this->insertNextCell().
387  * 
388  *  \if ENABLE_EXAMPLES
389  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
390  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
391  *  \endif
392  */
393 void MEDCouplingUMesh::finishInsertingCells()
394 {
395   _nodal_connec->pack();
396   _nodal_connec_index->pack();
397   _nodal_connec->declareAsNew();
398   _nodal_connec_index->declareAsNew();
399   updateTime();
400 }
401
402 /*!
403  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
404  * Useful for python users.
405  */
406 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
407 {
408   return new MEDCouplingUMeshCellIterator(this);
409 }
410
411 /*!
412  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
413  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
414  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
415  * Useful for python users.
416  */
417 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
418 {
419   if(!checkConsecutiveCellTypes())
420     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
421   return new MEDCouplingUMeshCellByTypeEntry(this);
422 }
423
424 /*!
425  * Returns a set of all cell types available in \a this mesh.
426  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
427  * \warning this method does not throw any exception even if \a this is not defined.
428  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
429  */
430 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
431 {
432   return _types;
433 }
434
435 /*!
436  * This method returns the sorted list of geometric types in \a this.
437  * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
438  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
439  *
440  * \throw if connectivity in \a this is not correctly defined.
441  *  
442  * \sa MEDCouplingMesh::getAllGeoTypes
443  */
444 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
445 {
446   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
447   checkConnectivityFullyDefined();
448   int nbOfCells(getNumberOfCells());
449   if(nbOfCells==0)
450     return ret;
451   if(getMeshLength()<1)
452     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
453   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
454   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
455   for(int i=1;i<nbOfCells;i++,ci++)
456     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
457       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
458   return ret;
459 }
460
461 /*!
462  * This method is a method that compares \a this and \a other.
463  * This method compares \b all attributes, even names and component names.
464  */
465 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
466 {
467   if(!other)
468     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
469   std::ostringstream oss; oss.precision(15);
470   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
471   if(!otherC)
472     {
473       reason="mesh given in input is not castable in MEDCouplingUMesh !";
474       return false;
475     }
476   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
477     return false;
478   if(_mesh_dim!=otherC->_mesh_dim)
479     {
480       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
481       reason=oss.str();
482       return false;
483     }
484   if(_types!=otherC->_types)
485     {
486       oss << "umesh geometric type mismatch :\nThis geometric types are :";
487       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
488         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
489       oss << "\nOther geometric types are :";
490       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
491         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
492       reason=oss.str();
493       return false;
494     }
495   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
496     if(_nodal_connec==0 || otherC->_nodal_connec==0)
497       {
498         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
499         return false;
500       }
501   if(_nodal_connec!=otherC->_nodal_connec)
502     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
503       {
504         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
505         return false;
506       }
507   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
508     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
509       {
510         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
511         return false;
512       }
513   if(_nodal_connec_index!=otherC->_nodal_connec_index)
514     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
515       {
516         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
517         return false;
518       }
519   return true;
520 }
521
522 /*!
523  * Checks if data arrays of this mesh (node coordinates, nodal
524  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
525  * not considered.
526  *  \param [in] other - the mesh to compare with.
527  *  \param [in] prec - precision value used to compare node coordinates.
528  *  \return bool - \a true if the two meshes are same.
529  */
530 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
531 {
532   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
533   if(!otherC)
534     return false;
535   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
536     return false;
537   if(_mesh_dim!=otherC->_mesh_dim)
538     return false;
539   if(_types!=otherC->_types)
540     return false;
541   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
542     if(_nodal_connec==0 || otherC->_nodal_connec==0)
543       return false;
544   if(_nodal_connec!=otherC->_nodal_connec)
545     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
546       return false;
547   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
548     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
549       return false;
550   if(_nodal_connec_index!=otherC->_nodal_connec_index)
551     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
552       return false;
553   return true;
554 }
555
556 /*!
557  * Checks if \a this and \a other meshes are geometrically equivalent with high
558  * probability, else an exception is thrown. The meshes are considered equivalent if
559  * (1) meshes contain the same number of nodes and the same number of elements of the
560  * same types (2) three cells of the two meshes (first, last and middle) are based
561  * on coincident nodes (with a specified precision).
562  *  \param [in] other - the mesh to compare with.
563  *  \param [in] prec - the precision used to compare nodes of the two meshes.
564  *  \throw If the two meshes do not match.
565  */
566 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
567 {
568   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
569   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
570   if(!otherC)
571     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
572 }
573
574 /*!
575  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
576  * cells each node belongs to.
577  * \warning For speed reasons, this method does not check if node ids in the nodal
578  *          connectivity correspond to the size of node coordinates array.
579  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
580  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
581  *        dividing cell ids in \a revNodal into groups each referring to one
582  *        node. Its every element (except the last one) is an index pointing to the
583  *         first id of a group of cells. For example cells sharing the node #1 are 
584  *        described by following range of indices: 
585  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
586  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
587  *        Number of cells sharing the *i*-th node is
588  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
589  * \throw If the coordinates array is not set.
590  * \throw If the nodal connectivity of cells is not defined.
591  * 
592  * \if ENABLE_EXAMPLES
593  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
594  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
595  * \endif
596  */
597 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
598 {
599   checkFullyDefined();
600   int nbOfNodes=getNumberOfNodes();
601   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
602   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
603   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
604   const int *conn=_nodal_connec->getConstPointer();
605   const int *connIndex=_nodal_connec_index->getConstPointer();
606   int nbOfCells=getNumberOfCells();
607   int nbOfEltsInRevNodal=0;
608   for(int eltId=0;eltId<nbOfCells;eltId++)
609     {
610       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
611       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
612       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
613         if(*iter>=0)//for polyhedrons
614           {
615             nbOfEltsInRevNodal++;
616             revNodalIndxPtr[(*iter)+1]++;
617           }
618     }
619   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
620   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
621   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
622   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
623   for(int eltId=0;eltId<nbOfCells;eltId++)
624     {
625       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
626       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
627       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
628         if(*iter>=0)//for polyhedrons
629           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
630     }
631 }
632
633 /// @cond INTERNAL
634
635 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
636 {
637   return id;
638 }
639
640 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
641 {
642   if(!compute)
643     return id+1;
644   else
645     {
646       if(cm.getOrientationStatus(nb,conn1,conn2))
647         return id+1;
648       else
649         return -(id+1);
650     }
651 }
652
653 class MinusOneSonsGenerator
654 {
655 public:
656   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
657   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
658   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
659   static const int DELTA=1;
660 private:
661   const INTERP_KERNEL::CellModel& _cm;
662 };
663
664 class MinusOneSonsGeneratorBiQuadratic
665 {
666 public:
667   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
668   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
669   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
670   static const int DELTA=1;
671 private:
672   const INTERP_KERNEL::CellModel& _cm;
673 };
674
675 class MinusTwoSonsGenerator
676 {
677 public:
678   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
679   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
680   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
681   static const int DELTA=2;
682 private:
683   const INTERP_KERNEL::CellModel& _cm;
684 };
685
686 /// @endcond
687
688 /*!
689  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
690  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
691  * describing correspondence between cells of \a this and the result meshes are
692  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
693  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
694  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
695  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
696  * \warning For speed reasons, this method does not check if node ids in the nodal
697  *          connectivity correspond to the size of node coordinates array.
698  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
699  *          to write this mesh to the MED file, its cells must be sorted using
700  *          sortCellsInMEDFileFrmt().
701  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
702  *         each cell of \a this mesh.
703  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
704  *        dividing cell ids in \a desc into groups each referring to one
705  *        cell of \a this mesh. Its every element (except the last one) is an index
706  *        pointing to the first id of a group of cells. For example cells of the
707  *        result mesh bounding the cell #1 of \a this mesh are described by following
708  *        range of indices:
709  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
710  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
711  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
712  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
713  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
714  *         by each cell of the result mesh.
715  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
716  *        in the result mesh,
717  *        dividing cell ids in \a revDesc into groups each referring to one
718  *        cell of the result mesh the same way as \a descIndx divides \a desc.
719  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
720  *        delete this mesh using decrRef() as it is no more needed.
721  *  \throw If the coordinates array is not set.
722  *  \throw If the nodal connectivity of cells is node defined.
723  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
724  *         revDescIndx == NULL.
725  * 
726  *  \if ENABLE_EXAMPLES
727  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
728  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
729  *  \endif
730  * \sa buildDescendingConnectivity2()
731  */
732 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
733 {
734   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
735 }
736
737 /*!
738  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
739  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
740  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
741  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
742  * \sa MEDCouplingUMesh::buildDescendingConnectivity
743  */
744 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
745 {
746   checkFullyDefined();
747   if(getMeshDimension()!=3)
748     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
749   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
750 }
751
752 /*!
753  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
754  * this->getMeshDimension(), that bound cells of \a this mesh. In
755  * addition arrays describing correspondence between cells of \a this and the result
756  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
757  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
758  *  mesh. This method differs from buildDescendingConnectivity() in that apart
759  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
760  * result meshes. So a positive id means that order of nodes in corresponding cells
761  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
762  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
763  * i.e. cell ids are one-based.
764  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
765  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
766  * \warning For speed reasons, this method does not check if node ids in the nodal
767  *          connectivity correspond to the size of node coordinates array.
768  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
769  *          to write this mesh to the MED file, its cells must be sorted using
770  *          sortCellsInMEDFileFrmt().
771  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
772  *         each cell of \a this mesh.
773  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
774  *        dividing cell ids in \a desc into groups each referring to one
775  *        cell of \a this mesh. Its every element (except the last one) is an index
776  *        pointing to the first id of a group of cells. For example cells of the
777  *        result mesh bounding the cell #1 of \a this mesh are described by following
778  *        range of indices:
779  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
780  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
781  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
782  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
783  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
784  *         by each cell of the result mesh.
785  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
786  *        in the result mesh,
787  *        dividing cell ids in \a revDesc into groups each referring to one
788  *        cell of the result mesh the same way as \a descIndx divides \a desc.
789  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
790  *        shares the node coordinates array with \a this mesh. The caller is to
791  *        delete this mesh using decrRef() as it is no more needed.
792  *  \throw If the coordinates array is not set.
793  *  \throw If the nodal connectivity of cells is node defined.
794  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
795  *         revDescIndx == NULL.
796  * 
797  *  \if ENABLE_EXAMPLES
798  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
799  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
800  *  \endif
801  * \sa buildDescendingConnectivity()
802  */
803 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
804 {
805   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
806 }
807
808 /*!
809  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
810  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
811  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
812  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
813  *
814  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
815  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
816  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
817  */
818 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
819 {
820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
821   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
823   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
824   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
825   meshDM1=0;
826   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
827 }
828
829 /*!
830  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
831  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
832  * excluding a set of meshdim-1 cells in input descending connectivity.
833  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
834  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
835  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
836  *
837  * \param [in] desc descending connectivity array.
838  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
839  * \param [in] revDesc reverse descending connectivity array.
840  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
841  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
842  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
843  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
844  */
845 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
846                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
847 {
848   if(!desc || !descIndx || !revDesc || !revDescIndx)
849     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
850   const int *descPtr=desc->getConstPointer();
851   const int *descIPtr=descIndx->getConstPointer();
852   const int *revDescPtr=revDesc->getConstPointer();
853   const int *revDescIPtr=revDescIndx->getConstPointer();
854   //
855   int nbCells=descIndx->getNumberOfTuples()-1;
856   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
857   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
858   int *out1Ptr=out1->getPointer();
859   *out1Ptr++=0;
860   out0->reserve(desc->getNumberOfTuples());
861   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
862     {
863       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
864         {
865           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
866           s.erase(i);
867           out0->insertAtTheEnd(s.begin(),s.end());
868         }
869       *out1Ptr=out0->getNumberOfTuples();
870     }
871   neighbors=out0.retn();
872   neighborsIndx=out1.retn();
873 }
874
875 /// @cond INTERNAL
876
877 /*!
878  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
879  * For speed reasons no check of this will be done.
880  */
881 template<class SonsGenerator>
882 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
883 {
884   if(!desc || !descIndx || !revDesc || !revDescIndx)
885     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
886   checkConnectivityFullyDefined();
887   int nbOfCells=getNumberOfCells();
888   int nbOfNodes=getNumberOfNodes();
889   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
890   int *revNodalIndxPtr=revNodalIndx->getPointer();
891   const int *conn=_nodal_connec->getConstPointer();
892   const int *connIndex=_nodal_connec_index->getConstPointer();
893   std::string name="Mesh constituent of "; name+=getName();
894   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
895   ret->setCoords(getCoords());
896   ret->allocateCells(2*nbOfCells);
897   descIndx->alloc(nbOfCells+1,1);
898   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
899   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
900   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
901     {
902       int pos=connIndex[eltId];
903       int posP1=connIndex[eltId+1];
904       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
905       SonsGenerator sg(cm);
906       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
907       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
908       for(unsigned i=0;i<nbOfSons;i++)
909         {
910           INTERP_KERNEL::NormalizedCellType cmsId;
911           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
912           for(unsigned k=0;k<nbOfNodesSon;k++)
913             if(tmp[k]>=0)
914               revNodalIndxPtr[tmp[k]+1]++;
915           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
916           revDesc2->pushBackSilent(eltId);
917         }
918       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
919     }
920   int nbOfCellsM1=ret->getNumberOfCells();
921   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
922   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
923   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
924   int *revNodalPtr=revNodal->getPointer();
925   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
926   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
927   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
928     {
929       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
930       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
931       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
932         if(*iter>=0)//for polyhedrons
933           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
934     }
935   //
936   DataArrayInt *commonCells=0,*commonCellsI=0;
937   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
938   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
939   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
940   int newNbOfCellsM1=-1;
941   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
942                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
943   std::vector<bool> isImpacted(nbOfCellsM1,false);
944   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
945     for(int work2=work[0];work2!=work[1];work2++)
946       isImpacted[commonCellsPtr[work2]]=true;
947   const int *o2nM1Ptr=o2nM1->getConstPointer();
948   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
949   const int *n2oM1Ptr=n2oM1->getConstPointer();
950   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
951   ret2->copyTinyInfoFrom(this);
952   desc->alloc(descIndx->back(),1);
953   int *descPtr=desc->getPointer();
954   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
955   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
956     {
957       if(!isImpacted[i])
958         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
959       else
960         {
961           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
962             {
963               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
964               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
965             }
966           else
967             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
968         }
969     }
970   revDesc->reserve(newNbOfCellsM1);
971   revDescIndx->alloc(newNbOfCellsM1+1,1);
972   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
973   const int *revDesc2Ptr=revDesc2->getConstPointer();
974   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
975     {
976       int oldCellIdM1=n2oM1Ptr[i];
977       if(!isImpacted[oldCellIdM1])
978         {
979           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
980           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
981         }
982       else
983         {
984           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
985             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
986           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
987           commonCellsIPtr++;
988         }
989     }
990   //
991   return ret2.retn();
992 }
993
994 struct MEDCouplingAccVisit
995 {
996   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
997   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
998   int _new_nb_of_nodes;
999 };
1000
1001 /// @endcond
1002
1003 /*!
1004  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1005  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1006  * array of cell ids. Pay attention that after conversion all algorithms work slower
1007  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1008  * conversion due presence of invalid ids in the array of cells to convert, as a
1009  * result \a this mesh contains some already converted elements. In this case the 2D
1010  * mesh remains valid but 3D mesh becomes \b inconsistent!
1011  *  \warning This method can significantly modify the order of geometric types in \a this,
1012  *          hence, to write this mesh to the MED file, its cells must be sorted using
1013  *          sortCellsInMEDFileFrmt().
1014  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1015  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1016  *         cellIdsToConvertBg.
1017  *  \throw If the coordinates array is not set.
1018  *  \throw If the nodal connectivity of cells is node defined.
1019  *  \throw If dimension of \a this mesh is not either 2 or 3.
1020  *
1021  *  \if ENABLE_EXAMPLES
1022  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1023  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1024  *  \endif
1025  */
1026 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1027 {
1028   checkFullyDefined();
1029   int dim=getMeshDimension();
1030   if(dim<2 || dim>3)
1031     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1032   int nbOfCells(getNumberOfCells());
1033   if(dim==2)
1034     {
1035       const int *connIndex=_nodal_connec_index->getConstPointer();
1036       int *conn=_nodal_connec->getPointer();
1037       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1038         {
1039           if(*iter>=0 && *iter<nbOfCells)
1040             {
1041               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1042               if(!cm.isQuadratic())
1043                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1044               else
1045                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1046             }
1047           else
1048             {
1049               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1050               oss << " in range [0," << nbOfCells << ") !";
1051               throw INTERP_KERNEL::Exception(oss.str().c_str());
1052             }
1053         }
1054     }
1055   else
1056     {
1057       int *connIndex(_nodal_connec_index->getPointer());
1058       const int *connOld(_nodal_connec->getConstPointer());
1059       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1060       std::vector<bool> toBeDone(nbOfCells,false);
1061       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1062         {
1063           if(*iter>=0 && *iter<nbOfCells)
1064             toBeDone[*iter]=true;
1065           else
1066             {
1067               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1068               oss << " in range [0," << nbOfCells << ") !";
1069               throw INTERP_KERNEL::Exception(oss.str().c_str());
1070             }
1071         }
1072       for(int cellId=0;cellId<nbOfCells;cellId++)
1073         {
1074           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1075           int lgthOld(posP1-pos-1);
1076           if(toBeDone[cellId])
1077             {
1078               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1079               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1080               int *tmp(new int[nbOfFaces*lgthOld+1]);
1081               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1082               for(unsigned j=0;j<nbOfFaces;j++)
1083                 {
1084                   INTERP_KERNEL::NormalizedCellType type;
1085                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1086                   work+=offset;
1087                   *work++=-1;
1088                 }
1089               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1090               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1091               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1092               delete [] tmp;
1093             }
1094           else
1095             {
1096               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1097               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1098             }
1099         }
1100       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1101     }
1102   computeTypes();
1103 }
1104
1105 /*!
1106  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1107  * polyhedrons (if \a this is a 3D mesh).
1108  *  \warning As this method is purely for user-friendliness and no optimization is
1109  *          done to avoid construction of a useless vector, this method can be costly
1110  *          in memory.
1111  *  \throw If the coordinates array is not set.
1112  *  \throw If the nodal connectivity of cells is node defined.
1113  *  \throw If dimension of \a this mesh is not either 2 or 3.
1114  */
1115 void MEDCouplingUMesh::convertAllToPoly()
1116 {
1117   int nbOfCells=getNumberOfCells();
1118   std::vector<int> cellIds(nbOfCells);
1119   for(int i=0;i<nbOfCells;i++)
1120     cellIds[i]=i;
1121   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1122 }
1123
1124 /*!
1125  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1126  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1127  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1128  * base facet of the volume and the second half of nodes describes an opposite facet
1129  * having the same number of nodes as the base one. This method converts such
1130  * connectivity to a valid polyhedral format where connectivity of each facet is
1131  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1132  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1133  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1134  * a correct orientation of the first facet of a polyhedron, else orientation of a
1135  * corrected cell is reverse.<br>
1136  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1137  * it releases the user from boring description of polyhedra connectivity in the valid
1138  * format.
1139  *  \throw If \a this->getMeshDimension() != 3.
1140  *  \throw If \a this->getSpaceDimension() != 3.
1141  *  \throw If the nodal connectivity of cells is not defined.
1142  *  \throw If the coordinates array is not set.
1143  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1144  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1145  *
1146  *  \if ENABLE_EXAMPLES
1147  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1148  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1149  *  \endif
1150  */
1151 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1152 {
1153   checkFullyDefined();
1154   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1155     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1156   int nbOfCells=getNumberOfCells();
1157   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1158   newCi->alloc(nbOfCells+1,1);
1159   int *newci=newCi->getPointer();
1160   const int *ci=_nodal_connec_index->getConstPointer();
1161   const int *c=_nodal_connec->getConstPointer();
1162   newci[0]=0;
1163   for(int i=0;i<nbOfCells;i++)
1164     {
1165       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1166       if(type==INTERP_KERNEL::NORM_POLYHED)
1167         {
1168           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1169             {
1170               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1171               throw INTERP_KERNEL::Exception(oss.str().c_str());
1172             }
1173           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1174           if(n2%2!=0)
1175             {
1176               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron with 1 face but there is a mismatch of number of nodes in face should be even !";
1177               throw INTERP_KERNEL::Exception(oss.str().c_str());
1178             }
1179           int n1=(int)(n2/2);
1180           newci[i+1]=7*n1+2+newci[i];//6*n1 (nodal length) + n1+2 (number of faces) - 1 (number of '-1' separator is equal to number of faces -1) + 1 (for cell type)
1181         }
1182       else
1183         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1184     }
1185   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1186   newC->alloc(newci[nbOfCells],1);
1187   int *newc=newC->getPointer();
1188   for(int i=0;i<nbOfCells;i++)
1189     {
1190       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1191       if(type==INTERP_KERNEL::NORM_POLYHED)
1192         {
1193           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1194           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1195           *newc++=-1;
1196           for(std::size_t j=0;j<n1;j++)
1197             {
1198               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1199               newc[n1+5*j]=-1;
1200               newc[n1+5*j+1]=c[ci[i]+1+j];
1201               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1202               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1203               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1204             }
1205           newc+=n1*6;
1206         }
1207       else
1208         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1209     }
1210   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1211   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1212 }
1213
1214
1215 /*!
1216  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1217  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1218  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1219  *          to write this mesh to the MED file, its cells must be sorted using
1220  *          sortCellsInMEDFileFrmt().
1221  * \return \c true if at least one cell has been converted, \c false else. In the
1222  *         last case the nodal connectivity remains unchanged.
1223  * \throw If the coordinates array is not set.
1224  * \throw If the nodal connectivity of cells is not defined.
1225  * \throw If \a this->getMeshDimension() < 0.
1226  */
1227 bool MEDCouplingUMesh::unPolyze()
1228 {
1229   checkFullyDefined();
1230   int mdim=getMeshDimension();
1231   if(mdim<0)
1232     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1233   if(mdim<=1)
1234     return false;
1235   int nbOfCells=getNumberOfCells();
1236   if(nbOfCells<1)
1237     return false;
1238   int initMeshLgth=getMeshLength();
1239   int *conn=_nodal_connec->getPointer();
1240   int *index=_nodal_connec_index->getPointer();
1241   int posOfCurCell=0;
1242   int newPos=0;
1243   int lgthOfCurCell;
1244   bool ret=false;
1245   for(int i=0;i<nbOfCells;i++)
1246     {
1247       lgthOfCurCell=index[i+1]-posOfCurCell;
1248       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1249       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1250       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1251       int newLgth;
1252       if(cm.isDynamic())
1253         {
1254           switch(cm.getDimension())
1255           {
1256             case 2:
1257               {
1258                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1259                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1260                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1261                 break;
1262               }
1263             case 3:
1264               {
1265                 int nbOfFaces,lgthOfPolyhConn;
1266                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1267                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1268                 break;
1269               }
1270             case 1:
1271               {
1272                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1273                 break;
1274               }
1275           }
1276           ret=ret || (newType!=type);
1277           conn[newPos]=newType;
1278           newPos+=newLgth+1;
1279           posOfCurCell=index[i+1];
1280           index[i+1]=newPos;
1281         }
1282       else
1283         {
1284           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1285           newPos+=lgthOfCurCell;
1286           posOfCurCell+=lgthOfCurCell;
1287           index[i+1]=newPos;
1288         }
1289     }
1290   if(newPos!=initMeshLgth)
1291     _nodal_connec->reAlloc(newPos);
1292   if(ret)
1293     computeTypes();
1294   return ret;
1295 }
1296
1297 /*!
1298  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1299  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1300  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1301  *
1302  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not. This epsilon is used to recenter around origin to have maximal 
1303  *             precision.
1304  */
1305 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1306 {
1307   checkFullyDefined();
1308   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1309     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1310   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1311   coords->recenterForMaxPrecision(eps);
1312   //
1313   int nbOfCells=getNumberOfCells();
1314   const int *conn=_nodal_connec->getConstPointer();
1315   const int *index=_nodal_connec_index->getConstPointer();
1316   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1317   connINew->alloc(nbOfCells+1,1);
1318   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1320   bool changed=false;
1321   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1322     {
1323       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1324         {
1325           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1326           changed=true;
1327         }
1328       else
1329         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1330       *connINewPtr=connNew->getNumberOfTuples();
1331     }
1332   if(changed)
1333     setConnectivity(connNew,connINew,false);
1334 }
1335
1336 /*!
1337  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1338  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1339  * the format of returned DataArrayInt instance.
1340  * 
1341  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1342  * \sa MEDCouplingUMesh::getNodeIdsInUse
1343  */
1344 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1345 {
1346   checkConnectivityFullyDefined();
1347   int nbOfCells=getNumberOfCells();
1348   const int *connIndex=_nodal_connec_index->getConstPointer();
1349   const int *conn=_nodal_connec->getConstPointer();
1350   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1351   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1352   std::vector<bool> retS(maxElt,false);
1353   for(int i=0;i<nbOfCells;i++)
1354     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1355       if(conn[j]>=0)
1356         retS[conn[j]]=true;
1357   int sz=0;
1358   for(int i=0;i<maxElt;i++)
1359     if(retS[i])
1360       sz++;
1361   DataArrayInt *ret=DataArrayInt::New();
1362   ret->alloc(sz,1);
1363   int *retPtr=ret->getPointer();
1364   for(int i=0;i<maxElt;i++)
1365     if(retS[i])
1366       *retPtr++=i;
1367   return ret;
1368 }
1369
1370 /*!
1371  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1372  * \sa MEDCouplingUMesh::getNodeIdsInUse
1373  */
1374 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1375 {
1376   int nbOfNodes=(int)nodeIdsInUse.size();
1377   int nbOfCells=getNumberOfCells();
1378   const int *connIndex=_nodal_connec_index->getConstPointer();
1379   const int *conn=_nodal_connec->getConstPointer();
1380   for(int i=0;i<nbOfCells;i++)
1381     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1382       if(conn[j]>=0)
1383         {
1384           if(conn[j]<nbOfNodes)
1385             nodeIdsInUse[conn[j]]=true;
1386           else
1387             {
1388               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1389               throw INTERP_KERNEL::Exception(oss.str().c_str());
1390             }
1391         }
1392 }
1393
1394 /*!
1395  * Finds nodes not used in any cell and returns an array giving a new id to every node
1396  * by excluding the unused nodes, for which the array holds -1. The result array is
1397  * a mapping in "Old to New" mode. 
1398  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1399  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1400  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1401  *          if the node is unused or a new id else. The caller is to delete this
1402  *          array using decrRef() as it is no more needed.  
1403  *  \throw If the coordinates array is not set.
1404  *  \throw If the nodal connectivity of cells is not defined.
1405  *  \throw If the nodal connectivity includes an invalid id.
1406  *
1407  *  \if ENABLE_EXAMPLES
1408  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1409  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1410  *  \endif
1411  * \sa computeNodeIdsAlg()
1412  */
1413 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1414 {
1415   nbrOfNodesInUse=-1;
1416   int nbOfNodes=getNumberOfNodes();
1417   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1418   ret->alloc(nbOfNodes,1);
1419   int *traducer=ret->getPointer();
1420   std::fill(traducer,traducer+nbOfNodes,-1);
1421   int nbOfCells=getNumberOfCells();
1422   const int *connIndex=_nodal_connec_index->getConstPointer();
1423   const int *conn=_nodal_connec->getConstPointer();
1424   for(int i=0;i<nbOfCells;i++)
1425     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1426       if(conn[j]>=0)
1427         {
1428           if(conn[j]<nbOfNodes)
1429             traducer[conn[j]]=1;
1430           else
1431             {
1432               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1433               throw INTERP_KERNEL::Exception(oss.str().c_str());
1434             }
1435         }
1436   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1437   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1438   return ret.retn();
1439 }
1440
1441 /*!
1442  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1443  * For each cell in \b this the number of nodes constituting cell is computed.
1444  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1445  * So for pohyhedrons some nodes can be counted several times in the returned result.
1446  * 
1447  * \return a newly allocated array
1448  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1449  */
1450 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1451 {
1452   checkConnectivityFullyDefined();
1453   int nbOfCells=getNumberOfCells();
1454   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1455   ret->alloc(nbOfCells,1);
1456   int *retPtr=ret->getPointer();
1457   const int *conn=getNodalConnectivity()->getConstPointer();
1458   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1459   for(int i=0;i<nbOfCells;i++,retPtr++)
1460     {
1461       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1462         *retPtr=connI[i+1]-connI[i]-1;
1463       else
1464         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1465     }
1466   return ret.retn();
1467 }
1468
1469 /*!
1470  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1471  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1472  *
1473  * \return DataArrayInt * - new object to be deallocated by the caller.
1474  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1475  */
1476 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1477 {
1478   checkConnectivityFullyDefined();
1479   int nbOfCells=getNumberOfCells();
1480   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1481   ret->alloc(nbOfCells,1);
1482   int *retPtr=ret->getPointer();
1483   const int *conn=getNodalConnectivity()->getConstPointer();
1484   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1485   for(int i=0;i<nbOfCells;i++,retPtr++)
1486     {
1487       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1488       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1489         *retPtr=(int)s.size();
1490       else
1491         {
1492           s.erase(-1);
1493           *retPtr=(int)s.size();
1494         }
1495     }
1496   return ret.retn();
1497 }
1498
1499 /*!
1500  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1501  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1502  * 
1503  * \return a newly allocated array
1504  */
1505 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1506 {
1507   checkConnectivityFullyDefined();
1508   int nbOfCells=getNumberOfCells();
1509   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1510   ret->alloc(nbOfCells,1);
1511   int *retPtr=ret->getPointer();
1512   const int *conn=getNodalConnectivity()->getConstPointer();
1513   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1514   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1515     {
1516       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1517       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1518     }
1519   return ret.retn();
1520 }
1521
1522 /*!
1523  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1524  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1525  * array mean that the corresponding old node is no more used. 
1526  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1527  *           this->getNumberOfNodes() before call of this method. The caller is to
1528  *           delete this array using decrRef() as it is no more needed. 
1529  *  \throw If the coordinates array is not set.
1530  *  \throw If the nodal connectivity of cells is not defined.
1531  *  \throw If the nodal connectivity includes an invalid id.
1532  *
1533  *  \if ENABLE_EXAMPLES
1534  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1535  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1536  *  \endif
1537  */
1538 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1539 {
1540   return MEDCouplingPointSet::zipCoordsTraducer();
1541 }
1542
1543 /*!
1544  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1545  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1546  */
1547 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1548 {
1549   switch(compType)
1550   {
1551     case 0:
1552       return AreCellsEqual0(conn,connI,cell1,cell2);
1553     case 1:
1554       return AreCellsEqual1(conn,connI,cell1,cell2);
1555     case 2:
1556       return AreCellsEqual2(conn,connI,cell1,cell2);
1557     case 3:
1558       return AreCellsEqual3(conn,connI,cell1,cell2);
1559     case 7:
1560       return AreCellsEqual7(conn,connI,cell1,cell2);
1561   }
1562   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1563 }
1564
1565 /*!
1566  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1567  */
1568 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1569 {
1570   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1571     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1572   return 0;
1573 }
1574
1575 /*!
1576  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1577  */
1578 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1579 {
1580   int sz=connI[cell1+1]-connI[cell1];
1581   if(sz==connI[cell2+1]-connI[cell2])
1582     {
1583       if(conn[connI[cell1]]==conn[connI[cell2]])
1584         {
1585           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1586           unsigned dim=cm.getDimension();
1587           if(dim!=3)
1588             {
1589               if(dim!=1)
1590                 {
1591                   int sz1=2*(sz-1);
1592                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1593                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1594                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1595                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1596                   return work!=tmp+sz1?1:0;
1597                 }
1598               else
1599                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1600             }
1601           else
1602             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1603         }
1604     }
1605   return 0;
1606 }
1607
1608 /*!
1609  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1610  */
1611 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1612 {
1613   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1614     {
1615       if(conn[connI[cell1]]==conn[connI[cell2]])
1616         {
1617           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1618           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1619           return s1==s2?1:0;
1620         }
1621     }
1622   return 0;
1623 }
1624
1625 /*!
1626  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1627  */
1628 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1629 {
1630   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1631     {
1632       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1633       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1634       return s1==s2?1:0;
1635     }
1636   return 0;
1637 }
1638
1639 /*!
1640  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1641  */
1642 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1643 {
1644   int sz=connI[cell1+1]-connI[cell1];
1645   if(sz==connI[cell2+1]-connI[cell2])
1646     {
1647       if(conn[connI[cell1]]==conn[connI[cell2]])
1648         {
1649           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1650           unsigned dim=cm.getDimension();
1651           if(dim!=3)
1652             {
1653               if(dim!=1)
1654                 {
1655                   int sz1=2*(sz-1);
1656                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1657                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1658                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1659                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1660                   if(work!=tmp+sz1)
1661                     return 1;
1662                   else
1663                     {
1664                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1665                       std::reverse_iterator<int *> it2((int *)tmp);
1666                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1667                         return 2;
1668                       else
1669                         return 0;
1670                     }
1671
1672                   return work!=tmp+sz1?1:0;
1673                 }
1674               else
1675                 {//case of SEG2 and SEG3
1676                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1677                     return 1;
1678                   if(!cm.isQuadratic())
1679                     {
1680                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1681                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1682                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1683                         return 2;
1684                       return 0;
1685                     }
1686                   else
1687                     {
1688                       if(conn[connI[cell1]+1]==conn[connI[cell2]+2] && conn[connI[cell1]+2]==conn[connI[cell2]+1] && conn[connI[cell1]+3]==conn[connI[cell2]+3])
1689                         return 2;
1690                       return 0;
1691                     }
1692                 }
1693             }
1694           else
1695             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1696         }
1697     }
1698   return 0;
1699 }
1700
1701 /*!
1702  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1703  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1704  * and result remains unchanged.
1705  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1706  * If in 'candidates' pool -1 value is considered as an empty value.
1707  * WARNING this method returns only ONE set of result !
1708  */
1709 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1710 {
1711   if(candidates.size()<1)
1712     return false;
1713   bool ret=false;
1714   std::vector<int>::const_iterator iter=candidates.begin();
1715   int start=(*iter++);
1716   for(;iter!=candidates.end();iter++)
1717     {
1718       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1719       if(status!=0)
1720         {
1721           if(!ret)
1722             {
1723               result->pushBackSilent(start);
1724               ret=true;
1725             }
1726           if(status==1)
1727             result->pushBackSilent(*iter);
1728           else
1729             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1730         }
1731     }
1732   return ret;
1733 }
1734
1735 /*!
1736  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1737  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1738  *
1739  * \param [in] compType input specifying the technique used to compare cells each other.
1740  *   - 0 : exactly. A cell is detected to be the same if and only if the connectivity is exactly the same without permutation and types same too. This is the strongest policy.
1741  *   - 1 : permutation same orientation. cell1 and cell2 are considered equal if the connectivity of cell2 can be deduced by those of cell1 by direct permutation (with exactly the same orientation)
1742  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1743  *   - 2 : nodal. cell1 and cell2 are equal if and only if cell1 and cell2 have same type and have the same nodes constituting connectivity. This is the laziest policy. This policy
1744  * can be used for users not sensitive to orientation of cell
1745  * \param [in] startCellId specifies the cellId starting from which the equality computation will be carried out. By default it is 0, which it means that all cells in \a this will be scanned.
1746  * \param [out] commonCells
1747  * \param [out] commonCellsI
1748  * \return the correspondance array old to new in a newly allocated array.
1749  * 
1750  */
1751 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1752 {
1753   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1754   getReverseNodalConnectivity(revNodal,revNodalI);
1755   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1756 }
1757
1758 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1759                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1760 {
1761   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1762   int nbOfCells=nodalI->getNumberOfTuples()-1;
1763   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1764   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1765   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1766   std::vector<bool> isFetched(nbOfCells,false);
1767   if(startCellId==0)
1768     {
1769       for(int i=0;i<nbOfCells;i++)
1770         {
1771           if(!isFetched[i])
1772             {
1773               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1774               std::vector<int> v,v2;
1775               if(connOfNode!=connPtr+connIPtr[i+1])
1776                 {
1777                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1778                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1779                   connOfNode++;
1780                 }
1781               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1782                 if(*connOfNode>=0)
1783                   {
1784                     v=v2;
1785                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1786                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1787                     v2.resize(std::distance(v2.begin(),it));
1788                   }
1789               if(v2.size()>1)
1790                 {
1791                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1792                     {
1793                       int pos=commonCellsI->back();
1794                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1795                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1796                         isFetched[*it]=true;
1797                     }
1798                 }
1799             }
1800         }
1801     }
1802   else
1803     {
1804       for(int i=startCellId;i<nbOfCells;i++)
1805         {
1806           if(!isFetched[i])
1807             {
1808               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1809               std::vector<int> v,v2;
1810               if(connOfNode!=connPtr+connIPtr[i+1])
1811                 {
1812                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1813                   connOfNode++;
1814                 }
1815               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1816                 if(*connOfNode>=0)
1817                   {
1818                     v=v2;
1819                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1820                     v2.resize(std::distance(v2.begin(),it));
1821                   }
1822               if(v2.size()>1)
1823                 {
1824                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1825                     {
1826                       int pos=commonCellsI->back();
1827                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1828                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1829                         isFetched[*it]=true;
1830                     }
1831                 }
1832             }
1833         }
1834     }
1835   commonCellsArr=commonCells.retn();
1836   commonCellsIArr=commonCellsI.retn();
1837 }
1838
1839 /*!
1840  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1841  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1842  * than \a other->getNumberOfCells() in the returned array means that there is no
1843  * corresponding cell in \a this mesh.
1844  * It is expected that \a this and \a other meshes share the same node coordinates
1845  * array, if it is not so an exception is thrown. 
1846  *  \param [in] other - the mesh to compare with.
1847  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1848  *         valid values [0,1,2], see zipConnectivityTraducer().
1849  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1850  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1851  *         values. The caller is to delete this array using
1852  *         decrRef() as it is no more needed.
1853  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1854  *         mesh.
1855  *
1856  *  \if ENABLE_EXAMPLES
1857  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1858  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1859  *  \endif
1860  *  \sa checkDeepEquivalOnSameNodesWith()
1861  *  \sa checkGeoEquivalWith()
1862  */
1863 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1864 {
1865   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1866   int nbOfCells=getNumberOfCells();
1867   static const int possibleCompType[]={0,1,2};
1868   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1869     {
1870       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1871       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1872       oss << " !";
1873       throw INTERP_KERNEL::Exception(oss.str().c_str());
1874     }
1875   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1876   arr=o2n->substr(nbOfCells);
1877   arr->setName(other->getName());
1878   int tmp;
1879   if(other->getNumberOfCells()==0)
1880     return true;
1881   return arr->getMaxValue(tmp)<nbOfCells;
1882 }
1883
1884 /*!
1885  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1886  * This method tries to determine if \b other is fully included in \b this.
1887  * The main difference is that this method is not expected to throw exception.
1888  * This method has two outputs :
1889  *
1890  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1891  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1892  */
1893 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1894 {
1895   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1896   DataArrayInt *commonCells=0,*commonCellsI=0;
1897   int thisNbCells=getNumberOfCells();
1898   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1899   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1900   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1901   int otherNbCells=other->getNumberOfCells();
1902   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1903   arr2->alloc(otherNbCells,1);
1904   arr2->fillWithZero();
1905   int *arr2Ptr=arr2->getPointer();
1906   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1907   for(int i=0;i<nbOfCommon;i++)
1908     {
1909       int start=commonCellsPtr[commonCellsIPtr[i]];
1910       if(start<thisNbCells)
1911         {
1912           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1913             {
1914               int sig=commonCellsPtr[j]>0?1:-1;
1915               int val=std::abs(commonCellsPtr[j])-1;
1916               if(val>=thisNbCells)
1917                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1918             }
1919         }
1920     }
1921   arr2->setName(other->getName());
1922   if(arr2->presenceOfValue(0))
1923     return false;
1924   arr=arr2.retn();
1925   return true;
1926 }
1927
1928 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1929 {
1930   if(!other)
1931     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1932   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1933   if(!otherC)
1934     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1935   std::vector<const MEDCouplingUMesh *> ms(2);
1936   ms[0]=this;
1937   ms[1]=otherC;
1938   return MergeUMeshesOnSameCoords(ms);
1939 }
1940
1941 /*!
1942  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1943  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1944  * cellIds is not given explicitely but by a range python like.
1945  * 
1946  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
1947  * \return a newly allocated
1948  * 
1949  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1950  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1951  */
1952 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
1953 {
1954   if(getMeshDimension()!=-1)
1955     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1956   else
1957     {
1958       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1959       if(newNbOfCells!=1)
1960         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1961       if(start!=0)
1962         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1963       incrRef();
1964       return const_cast<MEDCouplingUMesh *>(this);
1965     }
1966 }
1967
1968 /*!
1969  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1970  * The result mesh shares or not the node coordinates array with \a this mesh depending
1971  * on \a keepCoords parameter.
1972  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1973  *           to write this mesh to the MED file, its cells must be sorted using
1974  *           sortCellsInMEDFileFrmt().
1975  *  \param [in] begin - an array of cell ids to include to the new mesh.
1976  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1977  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1978  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1979  *         by calling zipCoords().
1980  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1981  *         to delete this mesh using decrRef() as it is no more needed. 
1982  *  \throw If the coordinates array is not set.
1983  *  \throw If the nodal connectivity of cells is not defined.
1984  *  \throw If any cell id in the array \a begin is not valid.
1985  *
1986  *  \if ENABLE_EXAMPLES
1987  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1988  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1989  *  \endif
1990  */
1991 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1992 {
1993   if(getMeshDimension()!=-1)
1994     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1995   else
1996     {
1997       if(end-begin!=1)
1998         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1999       if(begin[0]!=0)
2000         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2001       incrRef();
2002       return const_cast<MEDCouplingUMesh *>(this);
2003     }
2004 }
2005
2006 /*!
2007  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2008  *
2009  * This method allows to partially modify some cells in \b this (whose list is specified by [ \b cellIdsBg, \b cellIdsEnd ) ) with cells coming in \b otherOnSameCoordsThanThis.
2010  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2011  * The number of cells of \b this will remain the same with this method.
2012  *
2013  * \param [in] begin begin of cell ids (included) of cells in this to assign
2014  * \param [in] end end of cell ids (excluded) of cells in this to assign
2015  * \param [in] otherOnSameCoordsThanThis an another mesh with same meshdimension than \b this with exactly the same number of cells than cell ids list in [\b cellIdsBg, \b cellIdsEnd ).
2016  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2017  */
2018 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2019 {
2020   checkConnectivityFullyDefined();
2021   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2022   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2023     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2024   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2025     {
2026       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2027       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2028       throw INTERP_KERNEL::Exception(oss.str().c_str());
2029     }
2030   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2031   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2032     {
2033       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2034       throw INTERP_KERNEL::Exception(oss.str().c_str());
2035     }
2036   int nbOfCells=getNumberOfCells();
2037   bool easyAssign=true;
2038   const int *connI=_nodal_connec_index->getConstPointer();
2039   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2040   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2041     {
2042       if(*it>=0 && *it<nbOfCells)
2043         {
2044           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2045         }
2046       else
2047         {
2048           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2049           throw INTERP_KERNEL::Exception(oss.str().c_str());
2050         }
2051     }
2052   if(easyAssign)
2053     {
2054       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2055       computeTypes();
2056     }
2057   else
2058     {
2059       DataArrayInt *arrOut=0,*arrIOut=0;
2060       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2061                                                arrOut,arrIOut);
2062       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2063       setConnectivity(arrOut,arrIOut,true);
2064     }
2065 }
2066
2067 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2068 {
2069   checkConnectivityFullyDefined();
2070   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2071   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2072     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2073   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2074     {
2075       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2076       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2077       throw INTERP_KERNEL::Exception(oss.str().c_str());
2078     }
2079   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2080   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2081     {
2082       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2083       throw INTERP_KERNEL::Exception(oss.str().c_str());
2084     }
2085   int nbOfCells=getNumberOfCells();
2086   bool easyAssign=true;
2087   const int *connI=_nodal_connec_index->getConstPointer();
2088   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2089   int it=start;
2090   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2091     {
2092       if(it>=0 && it<nbOfCells)
2093         {
2094           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2095         }
2096       else
2097         {
2098           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2099           throw INTERP_KERNEL::Exception(oss.str().c_str());
2100         }
2101     }
2102   if(easyAssign)
2103     {
2104       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2105       computeTypes();
2106     }
2107   else
2108     {
2109       DataArrayInt *arrOut=0,*arrIOut=0;
2110       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2111                                                 arrOut,arrIOut);
2112       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2113       setConnectivity(arrOut,arrIOut,true);
2114     }
2115 }                      
2116
2117 /*!
2118  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2119  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2120  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2121  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2122  *
2123  * \param [in] begin input start of array of node ids.
2124  * \param [in] end input end of array of node ids.
2125  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2126  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2127  */
2128 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2129 {
2130   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2131   checkConnectivityFullyDefined();
2132   int tmp=-1;
2133   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2134   std::vector<bool> fastFinder(sz,false);
2135   for(const int *work=begin;work!=end;work++)
2136     if(*work>=0 && *work<sz)
2137       fastFinder[*work]=true;
2138   int nbOfCells=getNumberOfCells();
2139   const int *conn=getNodalConnectivity()->getConstPointer();
2140   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2141   for(int i=0;i<nbOfCells;i++)
2142     {
2143       int ref=0,nbOfHit=0;
2144       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2145         if(*work2>=0)
2146           {
2147             ref++;
2148             if(fastFinder[*work2])
2149               nbOfHit++;
2150           }
2151       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2152         cellIdsKept->pushBackSilent(i);
2153     }
2154   cellIdsKeptArr=cellIdsKept.retn();
2155 }
2156
2157 /*!
2158  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2159  * this->getMeshDimension(), that bound some cells of \a this mesh.
2160  * The cells of lower dimension to include to the result mesh are selected basing on
2161  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2162  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2163  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2164  * created mesh shares the node coordinates array with \a this mesh. 
2165  *  \param [in] begin - the array of node ids.
2166  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2167  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2168  *         array \a begin are added, else cells whose any node is in the
2169  *         array \a begin are added.
2170  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2171  *         to delete this mesh using decrRef() as it is no more needed. 
2172  *  \throw If the coordinates array is not set.
2173  *  \throw If the nodal connectivity of cells is not defined.
2174  *  \throw If any node id in \a begin is not valid.
2175  *
2176  *  \if ENABLE_EXAMPLES
2177  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2178  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2179  *  \endif
2180  */
2181 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2182 {
2183   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2184   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2185   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2186   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2187   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2188 }
2189
2190 /*!
2191  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2192  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2193  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2194  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2195  *         by calling zipCoords().
2196  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2197  *         to delete this mesh using decrRef() as it is no more needed. 
2198  *  \throw If the coordinates array is not set.
2199  *  \throw If the nodal connectivity of cells is not defined.
2200  *
2201  *  \if ENABLE_EXAMPLES
2202  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2203  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2204  *  \endif
2205  */
2206 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2207 {
2208   DataArrayInt *desc=DataArrayInt::New();
2209   DataArrayInt *descIndx=DataArrayInt::New();
2210   DataArrayInt *revDesc=DataArrayInt::New();
2211   DataArrayInt *revDescIndx=DataArrayInt::New();
2212   //
2213   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2214   revDesc->decrRef();
2215   desc->decrRef();
2216   descIndx->decrRef();
2217   int nbOfCells=meshDM1->getNumberOfCells();
2218   const int *revDescIndxC=revDescIndx->getConstPointer();
2219   std::vector<int> boundaryCells;
2220   for(int i=0;i<nbOfCells;i++)
2221     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2222       boundaryCells.push_back(i);
2223   revDescIndx->decrRef();
2224   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2225   return ret;
2226 }
2227
2228 /*!
2229  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2230  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2231  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2232  */
2233 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2234 {
2235   checkFullyDefined();
2236   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2238   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2239   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2240   //
2241   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2242   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2243   //
2244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2245   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2246   const int *revDescPtr=revDesc->getConstPointer();
2247   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2248   int nbOfCells=getNumberOfCells();
2249   std::vector<bool> ret1(nbOfCells,false);
2250   int sz=0;
2251   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2252     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2253       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2254   //
2255   DataArrayInt *ret2=DataArrayInt::New();
2256   ret2->alloc(sz,1);
2257   int *ret2Ptr=ret2->getPointer();
2258   sz=0;
2259   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2260     if(*it)
2261       *ret2Ptr++=sz;
2262   ret2->setName("BoundaryCells");
2263   return ret2;
2264 }
2265
2266 /*!
2267  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2268  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2269  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2270  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2271  *
2272  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2273  * This method method returns cells ids set s = s1 + s2 where :
2274  * 
2275  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2276  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2277  *
2278  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2279  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2280  *
2281  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2282  * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2283  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2284  */
2285 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2286 {
2287   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2288     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2289   checkConnectivityFullyDefined();
2290   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2291   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2292     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2293   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2294   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2295   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2296   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2297   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2298   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2299   DataArrayInt *idsOtherInConsti=0;
2300   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2301   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2302   if(!b)
2303     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2304   std::set<int> s1;
2305   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2306     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2308   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2309   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2310   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2311   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2312   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2313   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2314   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2315   neighThisPartAuto=0;
2316   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2317   const int li[2]={0,1};
2318   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2319   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2321   s_renum1->sort();
2322   //
2323   cellIdsRk0=s0arr.retn();
2324   cellIdsRk1=s_renum1.retn();
2325 }
2326
2327 /*!
2328  * This method computes the skin of \b this. That is to say the consituting meshdim-1 mesh is built and only the boundary subpart is
2329  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2330  * 
2331  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2332  */
2333 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2334 {
2335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2337   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2339   //
2340   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2341   revDesc=0; desc=0; descIndx=0;
2342   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2343   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2344   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2345 }
2346
2347 /*!
2348  * Finds nodes lying on the boundary of \a this mesh.
2349  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2350  *          nodes. The caller is to delete this array using decrRef() as it is no
2351  *          more needed.
2352  *  \throw If the coordinates array is not set.
2353  *  \throw If the nodal connectivity of cells is node defined.
2354  *
2355  *  \if ENABLE_EXAMPLES
2356  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2357  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2358  *  \endif
2359  */
2360 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2361 {
2362   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2363   return skin->computeFetchedNodeIds();
2364 }
2365
2366 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2367 {
2368   incrRef();
2369   return const_cast<MEDCouplingUMesh *>(this);
2370 }
2371
2372 /*!
2373  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2374  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2375  * This method searches for nodes needed to be duplicated. These nodes are nodes fetched by \b otherDimM1OnSameCoords which are not part of the boundary of \b otherDimM1OnSameCoords.
2376  * If a node is in the boundary of \b this \b and in the boundary of \b otherDimM1OnSameCoords this node is considerd as needed to be duplicated.
2377  * When the set of node ids \b nodeIdsToDuplicate is computed, cell ids in \b this is searched so that their connectivity includes at least 1 node in \b nodeIdsToDuplicate.
2378  *
2379  * \param [in] otherDimM1OnSameCoords a mesh lying on the same coords than \b this and with a mesh dimension equal to those of \b this minus 1. WARNING this input
2380  *             parameter is altered during the call.
2381  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2382  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2383  * \param [out] cellIdsNotModified cell ids int \b this that lies on \b otherDimM1OnSameCoords mesh whose connectivity do \b not need to be modified as it is the case for \b cellIdsNeededToBeRenum.
2384  *
2385  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2386  */
2387 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2388                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2389 {
2390   checkFullyDefined();
2391   otherDimM1OnSameCoords.checkFullyDefined();
2392   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2393     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2394   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2395     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2396   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2397   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2398   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2400   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2401   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2402   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2403   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2405   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2406   //
2407   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2408   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2409   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2410   DataArrayInt *idsTmp=0;
2411   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2412   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2413   if(!b)
2414     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2415   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2416   DataArrayInt *tmp0=0,*tmp1=0;
2417   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2418   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2419   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2420   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2421   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2422   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2423   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2424   //
2425   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2426   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2427   nodeIdsToDuplicate=s3.retn();
2428 }
2429
2430 /*!
2431  * This method operates a modification of the connectivity and coords in \b this.
2432  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2433  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2434  * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2435  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2436  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2437  * 
2438  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2439  * 
2440  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2441  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2442  */
2443 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2444 {
2445   int nbOfNodes=getNumberOfNodes();
2446   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2447   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2448 }
2449
2450 /*!
2451  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2452  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2453  * This method is a generalization of shiftNodeNumbersInConn().
2454  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2455  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2456  *         this->getNumberOfNodes(), in "Old to New" mode. 
2457  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2458  *  \throw If the nodal connectivity of cells is not defined.
2459  *
2460  *  \if ENABLE_EXAMPLES
2461  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2462  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2463  *  \endif
2464  */
2465 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2466 {
2467   checkConnectivityFullyDefined();
2468   int *conn=getNodalConnectivity()->getPointer();
2469   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2470   int nbOfCells=getNumberOfCells();
2471   for(int i=0;i<nbOfCells;i++)
2472     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2473       {
2474         int& node=conn[iconn];
2475         if(node>=0)//avoid polyhedron separator
2476           {
2477             node=newNodeNumbersO2N[node];
2478           }
2479       }
2480   _nodal_connec->declareAsNew();
2481   updateTime();
2482 }
2483
2484 /*!
2485  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2486  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2487  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2488  * 
2489  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2490  */
2491 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2492 {
2493   checkConnectivityFullyDefined();
2494   int *conn=getNodalConnectivity()->getPointer();
2495   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2496   int nbOfCells=getNumberOfCells();
2497   for(int i=0;i<nbOfCells;i++)
2498     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2499       {
2500         int& node=conn[iconn];
2501         if(node>=0)//avoid polyhedron separator
2502           {
2503             node+=delta;
2504           }
2505       }
2506   _nodal_connec->declareAsNew();
2507   updateTime();
2508 }
2509
2510 /*!
2511  * This method operates a modification of the connectivity in \b this.
2512  * Coordinates are \b NOT considered here and will remain unchanged by this method. this->_coords can ever been null for the needs of this method.
2513  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2514  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2515  * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2516  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2517  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2518  * 
2519  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2520  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2521  * 
2522  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2523  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2524  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2525  */
2526 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2527 {
2528   checkConnectivityFullyDefined();
2529   std::map<int,int> m;
2530   int val=offset;
2531   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2532     m[*work]=val;
2533   int *conn=getNodalConnectivity()->getPointer();
2534   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2535   int nbOfCells=getNumberOfCells();
2536   for(int i=0;i<nbOfCells;i++)
2537     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2538       {
2539         int& node=conn[iconn];
2540         if(node>=0)//avoid polyhedron separator
2541           {
2542             std::map<int,int>::iterator it=m.find(node);
2543             if(it!=m.end())
2544               node=(*it).second;
2545           }
2546       }
2547   updateTime();
2548 }
2549
2550 /*!
2551  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2552  *
2553  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2554  * After the call of this method the number of cells remains the same as before.
2555  *
2556  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2557  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2558  * be strictly in [0;this->getNumberOfCells()).
2559  *
2560  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2561  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2562  * should be contained in[0;this->getNumberOfCells()).
2563  * 
2564  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2565  */
2566 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2567 {
2568   checkConnectivityFullyDefined();
2569   int nbCells=getNumberOfCells();
2570   const int *array=old2NewBg;
2571   if(check)
2572     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2573   //
2574   const int *conn=_nodal_connec->getConstPointer();
2575   const int *connI=_nodal_connec_index->getConstPointer();
2576   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2577   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2578   const int *n2oPtr=n2o->begin();
2579   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2580   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2581   newConn->copyStringInfoFrom(*_nodal_connec);
2582   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2583   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2584   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2585   //
2586   int *newC=newConn->getPointer();
2587   int *newCI=newConnI->getPointer();
2588   int loc=0;
2589   newCI[0]=loc;
2590   for(int i=0;i<nbCells;i++)
2591     {
2592       int pos=n2oPtr[i];
2593       int nbOfElts=connI[pos+1]-connI[pos];
2594       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2595       loc+=nbOfElts;
2596       newCI[i+1]=loc;
2597     }
2598   //
2599   setConnectivity(newConn,newConnI);
2600   if(check)
2601     free(const_cast<int *>(array));
2602 }
2603
2604 /*!
2605  * Finds cells whose bounding boxes intersect a given bounding box.
2606  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2607  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2608  *         zMax (if in 3D). 
2609  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2610  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2611  *         extent of the bounding box of cell to produce an addition to this bounding box.
2612  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2613  *         cells. The caller is to delete this array using decrRef() as it is no more
2614  *         needed. 
2615  *  \throw If the coordinates array is not set.
2616  *  \throw If the nodal connectivity of cells is not defined.
2617  *
2618  *  \if ENABLE_EXAMPLES
2619  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2620  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2621  *  \endif
2622  */
2623 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2624 {
2625   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2626   if(getMeshDimension()==-1)
2627     {
2628       elems->pushBackSilent(0);
2629       return elems.retn();
2630     }
2631   int dim=getSpaceDimension();
2632   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2633   const int* conn      = getNodalConnectivity()->getConstPointer();
2634   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2635   const double* coords = getCoords()->getConstPointer();
2636   int nbOfCells=getNumberOfCells();
2637   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2638     {
2639       for (int i=0; i<dim; i++)
2640         {
2641           elem_bb[i*2]=std::numeric_limits<double>::max();
2642           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2643         }
2644
2645       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2646         {
2647           int node= conn[inode];
2648           if(node>=0)//avoid polyhedron separator
2649             {
2650               for (int idim=0; idim<dim; idim++)
2651                 {
2652                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2653                     {
2654                       elem_bb[idim*2] = coords[node*dim+idim] ;
2655                     }
2656                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2657                     {
2658                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2659                     }
2660                 }
2661             }
2662         }
2663       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2664         elems->pushBackSilent(ielem);
2665     }
2666   return elems.retn();
2667 }
2668
2669 /*!
2670  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2671  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2672  * added in 'elems' parameter.
2673  */
2674 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2675 {
2676   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2677   if(getMeshDimension()==-1)
2678     {
2679       elems->pushBackSilent(0);
2680       return elems.retn();
2681     }
2682   int dim=getSpaceDimension();
2683   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2684   const int* conn      = getNodalConnectivity()->getConstPointer();
2685   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2686   const double* coords = getCoords()->getConstPointer();
2687   int nbOfCells=getNumberOfCells();
2688   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2689     {
2690       for (int i=0; i<dim; i++)
2691         {
2692           elem_bb[i*2]=std::numeric_limits<double>::max();
2693           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2694         }
2695
2696       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2697         {
2698           int node= conn[inode];
2699           if(node>=0)//avoid polyhedron separator
2700             {
2701               for (int idim=0; idim<dim; idim++)
2702                 {
2703                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2704                     {
2705                       elem_bb[idim*2] = coords[node*dim+idim] ;
2706                     }
2707                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2708                     {
2709                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2710                     }
2711                 }
2712             }
2713         }
2714       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2715         elems->pushBackSilent(ielem);
2716     }
2717   return elems.retn();
2718 }
2719
2720 /*!
2721  * Returns a type of a cell by its id.
2722  *  \param [in] cellId - the id of the cell of interest.
2723  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2724  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2725  */
2726 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2727 {
2728   const int *ptI=_nodal_connec_index->getConstPointer();
2729   const int *pt=_nodal_connec->getConstPointer();
2730   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2731     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2732   else
2733     {
2734       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2735       throw INTERP_KERNEL::Exception(oss.str().c_str());
2736     }
2737 }
2738
2739 /*!
2740  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2741  * This method does not throw exception if geometric type \a type is not in \a this.
2742  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2743  * The coordinates array is not considered here.
2744  *
2745  * \param [in] type the geometric type
2746  * \return cell ids in this having geometric type \a type.
2747  */
2748 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2749 {
2750
2751   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2752   ret->alloc(0,1);
2753   checkConnectivityFullyDefined();
2754   int nbCells=getNumberOfCells();
2755   int mdim=getMeshDimension();
2756   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2757   if(mdim!=(int)cm.getDimension())
2758     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2759   const int *ptI=_nodal_connec_index->getConstPointer();
2760   const int *pt=_nodal_connec->getConstPointer();
2761   for(int i=0;i<nbCells;i++)
2762     {
2763       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2764         ret->pushBackSilent(i);
2765     }
2766   return ret.retn();
2767 }
2768
2769 /*!
2770  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2771  */
2772 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2773 {
2774   const int *ptI=_nodal_connec_index->getConstPointer();
2775   const int *pt=_nodal_connec->getConstPointer();
2776   int nbOfCells=getNumberOfCells();
2777   int ret=0;
2778   for(int i=0;i<nbOfCells;i++)
2779     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2780       ret++;
2781   return ret;
2782 }
2783
2784 /*!
2785  * Returns the nodal connectivity of a given cell.
2786  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2787  * all returned node ids can be used in getCoordinatesOfNode().
2788  *  \param [in] cellId - an id of the cell of interest.
2789  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2790  *         cleared before the appending.
2791  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2792  */
2793 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2794 {
2795   const int *ptI=_nodal_connec_index->getConstPointer();
2796   const int *pt=_nodal_connec->getConstPointer();
2797   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2798     if(*w>=0)
2799       conn.push_back(*w);
2800 }
2801
2802 std::string MEDCouplingUMesh::simpleRepr() const
2803 {
2804   static const char msg0[]="No coordinates specified !";
2805   std::ostringstream ret;
2806   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2807   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2808   int tmpp1,tmpp2;
2809   double tt=getTime(tmpp1,tmpp2);
2810   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2811   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2812   if(_mesh_dim>=-1)
2813     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2814   else
2815     { ret << " Mesh dimension has not been set or is invalid !"; }
2816   if(_coords!=0)
2817     {
2818       const int spaceDim=getSpaceDimension();
2819       ret << spaceDim << "\nInfo attached on space dimension : ";
2820       for(int i=0;i<spaceDim;i++)
2821         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2822       ret << "\n";
2823     }
2824   else
2825     ret << msg0 << "\n";
2826   ret << "Number of nodes : ";
2827   if(_coords!=0)
2828     ret << getNumberOfNodes() << "\n";
2829   else
2830     ret << msg0 << "\n";
2831   ret << "Number of cells : ";
2832   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2833     ret << getNumberOfCells() << "\n";
2834   else
2835     ret << "No connectivity specified !" << "\n";
2836   ret << "Cell types present : ";
2837   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2838     {
2839       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2840       ret << cm.getRepr() << " ";
2841     }
2842   ret << "\n";
2843   return ret.str();
2844 }
2845
2846 std::string MEDCouplingUMesh::advancedRepr() const
2847 {
2848   std::ostringstream ret;
2849   ret << simpleRepr();
2850   ret << "\nCoordinates array : \n___________________\n\n";
2851   if(_coords)
2852     _coords->reprWithoutNameStream(ret);
2853   else
2854     ret << "No array set !\n";
2855   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2856   reprConnectivityOfThisLL(ret);
2857   return ret.str();
2858 }
2859
2860 /*!
2861  * This method returns a C++ code that is a dump of \a this.
2862  * This method will throw if this is not fully defined.
2863  */
2864 std::string MEDCouplingUMesh::cppRepr() const
2865 {
2866   static const char coordsName[]="coords";
2867   static const char connName[]="conn";
2868   static const char connIName[]="connI";
2869   checkFullyDefined();
2870   std::ostringstream ret; ret << "// coordinates" << std::endl;
2871   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2872   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2873   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2874   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2875   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2876   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2877   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2878   return ret.str();
2879 }
2880
2881 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2882 {
2883   std::ostringstream ret;
2884   reprConnectivityOfThisLL(ret);
2885   return ret.str();
2886 }
2887
2888 /*!
2889  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2890  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2891  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2892  * some algos).
2893  * 
2894  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2895  * This method analyzes the 3 arrays of \a this. For each the following behaviour is done : if the array is null a newly one is created
2896  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2897  */
2898 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2899 {
2900   int mdim=getMeshDimension();
2901   if(mdim<0)
2902     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2903   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2904   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2905   bool needToCpyCT=true;
2906   if(!_nodal_connec)
2907     {
2908       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2909       needToCpyCT=false;
2910     }
2911   else
2912     {
2913       tmp1=_nodal_connec;
2914       tmp1->incrRef();
2915     }
2916   if(!_nodal_connec_index)
2917     {
2918       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2919       needToCpyCT=false;
2920     }
2921   else
2922     {
2923       tmp2=_nodal_connec_index;
2924       tmp2->incrRef();
2925     }
2926   ret->setConnectivity(tmp1,tmp2,false);
2927   if(needToCpyCT)
2928     ret->_types=_types;
2929   if(!_coords)
2930     {
2931       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2932       ret->setCoords(coords);
2933     }
2934   else
2935     ret->setCoords(_coords);
2936   return ret.retn();
2937 }
2938
2939 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2940 {
2941   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2942     {
2943       int nbOfCells=getNumberOfCells();
2944       const int *c=_nodal_connec->getConstPointer();
2945       const int *ci=_nodal_connec_index->getConstPointer();
2946       for(int i=0;i<nbOfCells;i++)
2947         {
2948           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2949           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2950           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2951           stream << "\n";
2952         }
2953     }
2954   else
2955     stream << "Connectivity not defined !\n";
2956 }
2957
2958 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2959 {
2960   const int *ptI=_nodal_connec_index->getConstPointer();
2961   const int *pt=_nodal_connec->getConstPointer();
2962   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2963     return ptI[cellId+1]-ptI[cellId]-1;
2964   else
2965     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2966 }
2967
2968 /*!
2969  * Returns types of cells of the specified part of \a this mesh.
2970  * This method avoids computing sub-mesh explicitely to get its types.
2971  *  \param [in] begin - an array of cell ids of interest.
2972  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2973  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2974  *         describing the cell types. 
2975  *  \throw If the coordinates array is not set.
2976  *  \throw If the nodal connectivity of cells is not defined.
2977  *  \sa getAllGeoTypes()
2978  */
2979 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
2980 {
2981   checkFullyDefined();
2982   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2983   const int *conn=_nodal_connec->getConstPointer();
2984   const int *connIndex=_nodal_connec_index->getConstPointer();
2985   for(const int *w=begin;w!=end;w++)
2986     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2987   return ret;
2988 }
2989
2990 /*!
2991  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2992  * a set of types of cells constituting \a this mesh. 
2993  * This method is for advanced users having prepared their connectivity before. For
2994  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2995  *  \param [in] conn - the nodal connectivity array. 
2996  *  \param [in] connIndex - the nodal connectivity index array.
2997  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2998  *         mesh is updated.
2999  */
3000 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3001 {
3002   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3003   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3004   if(isComputingTypes)
3005     computeTypes();
3006   declareAsNew();
3007 }
3008
3009 /*!
3010  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3011  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3012  */
3013 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3014     _nodal_connec(0),_nodal_connec_index(0),
3015     _types(other._types)
3016 {
3017   if(other._nodal_connec)
3018     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3019   if(other._nodal_connec_index)
3020     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3021 }
3022
3023 MEDCouplingUMesh::~MEDCouplingUMesh()
3024 {
3025   if(_nodal_connec)
3026     _nodal_connec->decrRef();
3027   if(_nodal_connec_index)
3028     _nodal_connec_index->decrRef();
3029 }
3030
3031 /*!
3032  * Recomputes a set of cell types of \a this mesh. For more info see
3033  * \ref MEDCouplingUMeshNodalConnectivity.
3034  */
3035 void MEDCouplingUMesh::computeTypes()
3036 {
3037   if(_nodal_connec && _nodal_connec_index)
3038     {
3039       _types.clear();
3040       const int *conn=_nodal_connec->getConstPointer();
3041       const int *connIndex=_nodal_connec_index->getConstPointer();
3042       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3043       if (nbOfElem > 0)
3044         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3045           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3046     }
3047 }
3048
3049 /*!
3050  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3051  */
3052 void MEDCouplingUMesh::checkFullyDefined() const
3053 {
3054   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3055     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3056 }
3057
3058 /*!
3059  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3060  */
3061 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3062 {
3063   if(!_nodal_connec_index || !_nodal_connec)
3064     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3065 }
3066
3067 /*!
3068  * Returns a number of cells constituting \a this mesh. 
3069  *  \return int - the number of cells in \a this mesh.
3070  *  \throw If the nodal connectivity of cells is not defined.
3071  */
3072 int MEDCouplingUMesh::getNumberOfCells() const
3073
3074   if(_nodal_connec_index)
3075     return _nodal_connec_index->getNumberOfTuples()-1;
3076   else
3077     if(_mesh_dim==-1)
3078       return 1;
3079     else
3080       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3081 }
3082
3083 /*!
3084  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3085  * mesh. For more info see \ref MEDCouplingMeshesPage.
3086  *  \return int - the dimension of \a this mesh.
3087  *  \throw If the mesh dimension is not defined using setMeshDimension().
3088  */
3089 int MEDCouplingUMesh::getMeshDimension() const
3090 {
3091   if(_mesh_dim<-1)
3092     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3093   return _mesh_dim;
3094 }
3095
3096 /*!
3097  * Returns a length of the nodal connectivity array.
3098  * This method is for test reason. Normally the integer returned is not useable by
3099  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3100  *  \return int - the length of the nodal connectivity array.
3101  */
3102 int MEDCouplingUMesh::getMeshLength() const
3103 {
3104   return _nodal_connec->getNbOfElems();
3105 }
3106
3107 /*!
3108  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3109  */
3110 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3111 {
3112   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3113   tinyInfo.push_back(getMeshDimension());
3114   tinyInfo.push_back(getNumberOfCells());
3115   if(_nodal_connec)
3116     tinyInfo.push_back(getMeshLength());
3117   else
3118     tinyInfo.push_back(-1);
3119 }
3120
3121 /*!
3122  * First step of unserialization process.
3123  */
3124 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3125 {
3126   return tinyInfo[6]<=0;
3127 }
3128
3129 /*!
3130  * Second step of serialization process.
3131  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3132  */
3133 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3134 {
3135   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3136   if(tinyInfo[5]!=-1)
3137     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3138 }
3139
3140 /*!
3141  * Third and final step of serialization process.
3142  */
3143 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3144 {
3145   MEDCouplingPointSet::serialize(a1,a2);
3146   if(getMeshDimension()>-1)
3147     {
3148       a1=DataArrayInt::New();
3149       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3150       int *ptA1=a1->getPointer();
3151       const int *conn=getNodalConnectivity()->getConstPointer();
3152       const int *index=getNodalConnectivityIndex()->getConstPointer();
3153       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3154       std::copy(conn,conn+getMeshLength(),ptA1);
3155     }
3156   else
3157     a1=0;
3158 }
3159
3160 /*!
3161  * Second and final unserialization process.
3162  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3163  */
3164 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3165 {
3166   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3167   setMeshDimension(tinyInfo[5]);
3168   if(tinyInfo[7]!=-1)
3169     {
3170       // Connectivity
3171       const int *recvBuffer=a1->getConstPointer();
3172       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3173       myConnecIndex->alloc(tinyInfo[6]+1,1);
3174       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3175       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3176       myConnec->alloc(tinyInfo[7],1);
3177       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3178       setConnectivity(myConnec, myConnecIndex);
3179     }
3180 }
3181
3182 /*!
3183  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3184  * CellIds are given using range specified by a start an end and step.
3185  */
3186 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3187 {
3188   checkFullyDefined();
3189   int ncell=getNumberOfCells();
3190   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3191   ret->_mesh_dim=_mesh_dim;
3192   ret->setCoords(_coords);
3193   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3194   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3195   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3196   int work=start;
3197   const int *conn=_nodal_connec->getConstPointer();
3198   const int *connIndex=_nodal_connec_index->getConstPointer();
3199   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3200     {
3201       if(work>=0 && work<ncell)
3202         {
3203           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3204         }
3205       else
3206         {
3207           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3208           throw INTERP_KERNEL::Exception(oss.str().c_str());
3209         }
3210     }
3211   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3212   int *newConnPtr=newConn->getPointer();
3213   std::set<INTERP_KERNEL::NormalizedCellType> types;
3214   work=start;
3215   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3216     {
3217       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3218       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3219     }
3220   ret->setConnectivity(newConn,newConnI,false);
3221   ret->_types=types;
3222   ret->copyTinyInfoFrom(this);
3223   return ret.retn();
3224 }
3225
3226 /*!
3227  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3228  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3229  * The return newly allocated mesh will share the same coordinates as \a this.
3230  */
3231 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3232 {
3233   checkConnectivityFullyDefined();
3234   int ncell=getNumberOfCells();
3235   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3236   ret->_mesh_dim=_mesh_dim;
3237   ret->setCoords(_coords);
3238   std::size_t nbOfElemsRet=std::distance(begin,end);
3239   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3240   connIndexRet[0]=0;
3241   const int *conn=_nodal_connec->getConstPointer();
3242   const int *connIndex=_nodal_connec_index->getConstPointer();
3243   int newNbring=0;
3244   for(const int *work=begin;work!=end;work++,newNbring++)
3245     {
3246       if(*work>=0 && *work<ncell)
3247         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3248       else
3249         {
3250           free(connIndexRet);
3251           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3252           throw INTERP_KERNEL::Exception(oss.str().c_str());
3253         }
3254     }
3255   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3256   int *connRetWork=connRet;
3257   std::set<INTERP_KERNEL::NormalizedCellType> types;
3258   for(const int *work=begin;work!=end;work++)
3259     {
3260       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3261       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3262     }
3263   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3264   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3265   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3266   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3267   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3268   ret->_types=types;
3269   ret->copyTinyInfoFrom(this);
3270   return ret.retn();
3271 }
3272
3273 /*!
3274  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3275  * mesh.<br>
3276  * For 1D cells, the returned field contains lengths.<br>
3277  * For 2D cells, the returned field contains areas.<br>
3278  * For 3D cells, the returned field contains volumes.
3279  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3280  *         orientation, i.e. the volume is always positive.
3281  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3282  *         and one time . The caller is to delete this field using decrRef() as it is no
3283  *         more needed.
3284  */
3285 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3286 {
3287   std::string name="MeasureOfMesh_";
3288   name+=getName();
3289   int nbelem=getNumberOfCells();
3290   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3291   field->setName(name);
3292   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3293   array->alloc(nbelem,1);
3294   double *area_vol=array->getPointer();
3295   field->setArray(array) ; array=0;
3296   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3297   field->synchronizeTimeWithMesh();
3298   if(getMeshDimension()!=-1)
3299     {
3300       int ipt;
3301       INTERP_KERNEL::NormalizedCellType type;
3302       int dim_space=getSpaceDimension();
3303       const double *coords=getCoords()->getConstPointer();
3304       const int *connec=getNodalConnectivity()->getConstPointer();
3305       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3306       for(int iel=0;iel<nbelem;iel++)
3307         {
3308           ipt=connec_index[iel];
3309           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3310           area_vol[iel]=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[iel+1]-ipt-1,coords,dim_space);
3311         }
3312       if(isAbs)
3313         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3314     }
3315   else
3316     {
3317       area_vol[0]=std::numeric_limits<double>::max();
3318     }
3319   return field.retn();
3320 }
3321
3322 /*!
3323  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3324  * mesh.<br>
3325  * For 1D cells, the returned array contains lengths.<br>
3326  * For 2D cells, the returned array contains areas.<br>
3327  * For 3D cells, the returned array contains volumes.
3328  * This method avoids building explicitly a part of \a this mesh to perform the work.
3329  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3330  *         orientation, i.e. the volume is always positive.
3331  *  \param [in] begin - an array of cell ids of interest.
3332  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3333  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3334  *          delete this array using decrRef() as it is no more needed.
3335  * 
3336  *  \if ENABLE_EXAMPLES
3337  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3338  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3339  *  \endif
3340  *  \sa getMeasureField()
3341  */
3342 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3343 {
3344   std::string name="PartMeasureOfMesh_";
3345   name+=getName();
3346   int nbelem=(int)std::distance(begin,end);
3347   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3348   array->setName(name);
3349   array->alloc(nbelem,1);
3350   double *area_vol=array->getPointer();
3351   if(getMeshDimension()!=-1)
3352     {
3353       int ipt;
3354       INTERP_KERNEL::NormalizedCellType type;
3355       int dim_space=getSpaceDimension();
3356       const double *coords=getCoords()->getConstPointer();
3357       const int *connec=getNodalConnectivity()->getConstPointer();
3358       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3359       for(const int *iel=begin;iel!=end;iel++)
3360         {
3361           ipt=connec_index[*iel];
3362           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3363           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3364         }
3365       if(isAbs)
3366         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3367     }
3368   else
3369     {
3370       area_vol[0]=std::numeric_limits<double>::max();
3371     }
3372   return array.retn();
3373 }
3374
3375 /*!
3376  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3377  * \a this one. The returned field contains the dual cell volume for each corresponding
3378  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3379  *  the dual mesh in P1 sens of \a this.<br>
3380  * For 1D cells, the returned field contains lengths.<br>
3381  * For 2D cells, the returned field contains areas.<br>
3382  * For 3D cells, the returned field contains volumes.
3383  * This method is useful to check "P1*" conservative interpolators.
3384  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3385  *         orientation, i.e. the volume is always positive.
3386  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3387  *          nodes and one time. The caller is to delete this array using decrRef() as
3388  *          it is no more needed.
3389  */
3390 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3391 {
3392   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3393   std::string name="MeasureOnNodeOfMesh_";
3394   name+=getName();
3395   int nbNodes=getNumberOfNodes();
3396   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3397   double cst=1./((double)getMeshDimension()+1.);
3398   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3399   array->alloc(nbNodes,1);
3400   double *valsToFill=array->getPointer();
3401   std::fill(valsToFill,valsToFill+nbNodes,0.);
3402   const double *values=tmp->getArray()->getConstPointer();
3403   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3405   getReverseNodalConnectivity(da,daInd);
3406   const int *daPtr=da->getConstPointer();
3407   const int *daIPtr=daInd->getConstPointer();
3408   for(int i=0;i<nbNodes;i++)
3409     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3410       valsToFill[i]+=cst*values[*cell];
3411   ret->setMesh(this);
3412   ret->setArray(array);
3413   return ret.retn();
3414 }
3415
3416 /*!
3417  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3418  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3419  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3420  * and are normalized.
3421  * <br> \a this can be either 
3422  * - a  2D mesh in 2D or 3D space or 
3423  * - an 1D mesh in 2D space.
3424  * 
3425  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3426  *          cells and one time. The caller is to delete this field using decrRef() as
3427  *          it is no more needed.
3428  *  \throw If the nodal connectivity of cells is not defined.
3429  *  \throw If the coordinates array is not set.
3430  *  \throw If the mesh dimension is not set.
3431  *  \throw If the mesh and space dimension is not as specified above.
3432  */
3433 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3434 {
3435   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3436     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3437   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3438   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3439   int nbOfCells=getNumberOfCells();
3440   int nbComp=getMeshDimension()+1;
3441   array->alloc(nbOfCells,nbComp);
3442   double *vals=array->getPointer();
3443   const int *connI=_nodal_connec_index->getConstPointer();
3444   const int *conn=_nodal_connec->getConstPointer();
3445   const double *coords=_coords->getConstPointer();
3446   if(getMeshDimension()==2)
3447     {
3448       if(getSpaceDimension()==3)
3449         {
3450           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3451           const double *locPtr=loc->getConstPointer();
3452           for(int i=0;i<nbOfCells;i++,vals+=3)
3453             {
3454               int offset=connI[i];
3455               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3456               double n=INTERP_KERNEL::norm<3>(vals);
3457               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3458             }
3459         }
3460       else
3461         {
3462           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3463           const double *isAbsPtr=isAbs->getArray()->begin();
3464           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3465             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3466         }
3467     }
3468   else//meshdimension==1
3469     {
3470       double tmp[2];
3471       for(int i=0;i<nbOfCells;i++)
3472         {
3473           int offset=connI[i];
3474           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3475           double n=INTERP_KERNEL::norm<2>(tmp);
3476           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3477           *vals++=-tmp[1];
3478           *vals++=tmp[0];
3479         }
3480     }
3481   ret->setArray(array);
3482   ret->setMesh(this);
3483   ret->synchronizeTimeWithSupport();
3484   return ret.retn();
3485 }
3486
3487 /*!
3488  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3489  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3490  * and are normalized.
3491  * <br> \a this can be either 
3492  * - a  2D mesh in 2D or 3D space or 
3493  * - an 1D mesh in 2D space.
3494  * 
3495  * This method avoids building explicitly a part of \a this mesh to perform the work.
3496  *  \param [in] begin - an array of cell ids of interest.
3497  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3498  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3499  *          cells and one time. The caller is to delete this field using decrRef() as
3500  *          it is no more needed.
3501  *  \throw If the nodal connectivity of cells is not defined.
3502  *  \throw If the coordinates array is not set.
3503  *  \throw If the mesh dimension is not set.
3504  *  \throw If the mesh and space dimension is not as specified above.
3505  *  \sa buildOrthogonalField()
3506  *
3507  *  \if ENABLE_EXAMPLES
3508  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3509  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3510  *  \endif
3511  */
3512 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3513 {
3514   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3515     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3516   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3517   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3518   std::size_t nbelems=std::distance(begin,end);
3519   int nbComp=getMeshDimension()+1;
3520   array->alloc((int)nbelems,nbComp);
3521   double *vals=array->getPointer();
3522   const int *connI=_nodal_connec_index->getConstPointer();
3523   const int *conn=_nodal_connec->getConstPointer();
3524   const double *coords=_coords->getConstPointer();
3525   if(getMeshDimension()==2)
3526     {
3527       if(getSpaceDimension()==3)
3528         {
3529           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3530           const double *locPtr=loc->getConstPointer();
3531           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3532             {
3533               int offset=connI[*i];
3534               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3535               double n=INTERP_KERNEL::norm<3>(vals);
3536               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3537             }
3538         }
3539       else
3540         {
3541           for(std::size_t i=0;i<nbelems;i++)
3542             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3543         }
3544     }
3545   else//meshdimension==1
3546     {
3547       double tmp[2];
3548       for(const int *i=begin;i!=end;i++)
3549         {
3550           int offset=connI[*i];
3551           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3552           double n=INTERP_KERNEL::norm<2>(tmp);
3553           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3554           *vals++=-tmp[1];
3555           *vals++=tmp[0];
3556         }
3557     }
3558   ret->setArray(array);
3559   ret->setMesh(this);
3560   ret->synchronizeTimeWithSupport();
3561   return ret.retn();
3562 }
3563
3564 /*!
3565  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3566  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3567  * and are \b not normalized.
3568  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3569  *          cells and one time. The caller is to delete this field using decrRef() as
3570  *          it is no more needed.
3571  *  \throw If the nodal connectivity of cells is not defined.
3572  *  \throw If the coordinates array is not set.
3573  *  \throw If \a this->getMeshDimension() != 1.
3574  *  \throw If \a this mesh includes cells of type other than SEG2.
3575  */
3576 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3577 {
3578   if(getMeshDimension()!=1)
3579     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3580   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3581     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3582   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3583   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3584   int nbOfCells=getNumberOfCells();
3585   int spaceDim=getSpaceDimension();
3586   array->alloc(nbOfCells,spaceDim);
3587   double *pt=array->getPointer();
3588   const double *coo=getCoords()->getConstPointer();
3589   std::vector<int> conn;
3590   conn.reserve(2);
3591   for(int i=0;i<nbOfCells;i++)
3592     {
3593       conn.resize(0);
3594       getNodeIdsOfCell(i,conn);
3595       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3596     }
3597   ret->setArray(array);
3598   ret->setMesh(this);
3599   ret->synchronizeTimeWithSupport();
3600   return ret.retn();
3601 }
3602
3603 /*!
3604  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3605  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3606  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3607  * from. If a result face is shared by two 3D cells, then the face in included twice in
3608  * the result mesh.
3609  *  \param [in] origin - 3 components of a point defining location of the plane.
3610  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3611  *         must be greater than 1e-6.
3612  *  \param [in] eps - half-thickness of the plane.
3613  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3614  *         producing correspondent 2D cells. The caller is to delete this array
3615  *         using decrRef() as it is no more needed.
3616  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3617  *         not share the node coordinates array with \a this mesh. The caller is to
3618  *         delete this mesh using decrRef() as it is no more needed.  
3619  *  \throw If the coordinates array is not set.
3620  *  \throw If the nodal connectivity of cells is not defined.
3621  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3622  *  \throw If magnitude of \a vec is less than 1e-6.
3623  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3624  *  \throw If \a this includes quadratic cells.
3625  */
3626 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3627 {
3628   checkFullyDefined();
3629   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3630     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3631   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3632   if(candidates->empty())
3633     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3634   std::vector<int> nodes;
3635   DataArrayInt *cellIds1D=0;
3636   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3637   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3638   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3639   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3640   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3641   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3642   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3643   revDesc2=0; revDescIndx2=0;
3644   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3645   revDesc1=0; revDescIndx1=0;
3646   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3647   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3648   //
3649   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3650   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3651     cut3DCurve[*it]=-1;
3652   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3653   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3654   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3655                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3656                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3657   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3658   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3659   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3660   if(cellIds2->empty())
3661     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3662   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3663   ret->setCoords(mDesc1->getCoords());
3664   ret->setConnectivity(conn,connI,true);
3665   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3666   return ret.retn();
3667 }
3668
3669 /*!
3670  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3671 addition to the mesh, returns a new DataArrayInt, of length equal to the number of 1D cells in the result mesh, holding, for each cell in the result mesh, an id of a 2D cell it comes
3672 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3673 the result mesh.
3674  *  \param [in] origin - 3 components of a point defining location of the plane.
3675  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3676  *         must be greater than 1e-6.
3677  *  \param [in] eps - half-thickness of the plane.
3678  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3679  *         producing correspondent segments. The caller is to delete this array
3680  *         using decrRef() as it is no more needed.
3681  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3682  *         mesh in 3D space. This mesh does not share the node coordinates array with
3683  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3684  *         no more needed. 
3685  *  \throw If the coordinates array is not set.
3686  *  \throw If the nodal connectivity of cells is not defined.
3687  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3688  *  \throw If magnitude of \a vec is less than 1e-6.
3689  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3690  *  \throw If \a this includes quadratic cells.
3691  */
3692 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3693 {
3694   checkFullyDefined();
3695   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3696     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3697   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3698   if(candidates->empty())
3699     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3700   std::vector<int> nodes;
3701   DataArrayInt *cellIds1D=0;
3702   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3703   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3704   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3705   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3706   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3707   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3708   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3709   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3710   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3711   //
3712   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3713   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3714     cut3DCurve[*it]=-1;
3715   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3716   int ncellsSub=subMesh->getNumberOfCells();
3717   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3718   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3719                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3720                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3721   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3722   conn->alloc(0,1);
3723   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3724   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3725   for(int i=0;i<ncellsSub;i++)
3726     {
3727       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3728         {
3729           if(cut3DSurf[i].first!=-2)
3730             {
3731               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3732               connI->pushBackSilent(conn->getNumberOfTuples());
3733               cellIds2->pushBackSilent(i);
3734             }
3735           else
3736             {
3737               int cellId3DSurf=cut3DSurf[i].second;
3738               int offset=nodalI[cellId3DSurf]+1;
3739               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3740               for(int j=0;j<nbOfEdges;j++)
3741                 {
3742                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3743                   connI->pushBackSilent(conn->getNumberOfTuples());
3744                   cellIds2->pushBackSilent(cellId3DSurf);
3745                 }
3746             }
3747         }
3748     }
3749   if(cellIds2->empty())
3750     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3751   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3752   ret->setCoords(mDesc1->getCoords());
3753   ret->setConnectivity(conn,connI,true);
3754   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3755   return ret.retn();
3756 }
3757
3758 /*!
3759  * Finds cells whose bounding boxes intersect a given plane.
3760  *  \param [in] origin - 3 components of a point defining location of the plane.
3761  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3762  *         must be greater than 1e-6.
3763  *  \param [in] eps - half-thickness of the plane.
3764  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3765  *         cells. The caller is to delete this array using decrRef() as it is no more
3766  *         needed.
3767  *  \throw If the coordinates array is not set.
3768  *  \throw If the nodal connectivity of cells is not defined.
3769  *  \throw If \a this->getSpaceDimension() != 3.
3770  *  \throw If magnitude of \a vec is less than 1e-6.
3771  *  \sa buildSlice3D()
3772  */
3773 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3774 {
3775   checkFullyDefined();
3776   if(getSpaceDimension()!=3)
3777     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3778   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3779   if(normm<1e-6)
3780     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3781   double vec2[3];
3782   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3783   double angle=acos(vec[2]/normm);
3784   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3785   double bbox[6];
3786   if(angle>eps)
3787     {
3788       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3789       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3790       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3791       mw->setCoords(coo);
3792       mw->getBoundingBox(bbox);
3793       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3794       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3795     }
3796   else
3797     {
3798       getBoundingBox(bbox);
3799       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3800       cellIds=getCellsInBoundingBox(bbox,eps);
3801     }
3802   return cellIds.retn();
3803 }
3804
3805 /*!
3806  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3807  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3808  * No consideration of coordinate is done by this method.
3809  * A 1D mesh is said contiguous if : a cell i with nodal connectivity (k,p) the cell i+1 the nodal connectivity should be (p,m)
3810  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3811  */
3812 bool MEDCouplingUMesh::isContiguous1D() const
3813 {
3814   if(getMeshDimension()!=1)
3815     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3816   int nbCells=getNumberOfCells();
3817   if(nbCells<1)
3818     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3819   const int *connI=_nodal_connec_index->getConstPointer();
3820   const int *conn=_nodal_connec->getConstPointer();
3821   int ref=conn[connI[0]+2];
3822   for(int i=1;i<nbCells;i++)
3823     {
3824       if(conn[connI[i]+1]!=ref)
3825         return false;
3826       ref=conn[connI[i]+2];
3827     }
3828   return true;
3829 }
3830
3831 /*!
3832  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3833  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3834  * \param pt reference point of the line
3835  * \param v normalized director vector of the line
3836  * \param eps max precision before throwing an exception
3837  * \param res output of size this->getNumberOfCells
3838  */
3839 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3840 {
3841   if(getMeshDimension()!=1)
3842     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3843   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3844     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3845   if(getSpaceDimension()!=3)
3846     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3847   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3848   const double *fPtr=f->getArray()->getConstPointer();
3849   double tmp[3];
3850   for(int i=0;i<getNumberOfCells();i++)
3851     {
3852       const double *tmp1=fPtr+3*i;
3853       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3854       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3855       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3856       double n1=INTERP_KERNEL::norm<3>(tmp);
3857       n1/=INTERP_KERNEL::norm<3>(tmp1);
3858       if(n1>eps)
3859         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3860     }
3861   const double *coo=getCoords()->getConstPointer();
3862   for(int i=0;i<getNumberOfNodes();i++)
3863     {
3864       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3865       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3866       res[i]=std::accumulate(tmp,tmp+3,0.);
3867     }
3868 }
3869
3870 /*!
3871  * This method computes the distance from a point \a pt to \a this and the first \a cellId in \a this corresponding to the returned distance. 
3872  * \a this is expected to be a mesh so that its space dimension is equal to its
3873  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3874  * Distance from \a ptBg to \a ptEnd is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
3875  *
3876  * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3877  * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3878  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3879  *
3880  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3881  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3882  *
3883  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3884  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3885  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3886  * \return the positive value of the distance.
3887  * \throw if distance from \a ptBg to \a ptEnd is not equal to the space dimension. An exception is also thrown if mesh dimension of \a this is not equal to space
3888  * dimension - 1.
3889  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3890  */
3891 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3892 {
3893   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3894   if(meshDim!=spaceDim-1)
3895     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3896   if(meshDim!=2 && meshDim!=1)
3897     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3898   checkFullyDefined();
3899   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3900     { std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoint : input point has to have dimension equal to the space dimension of this (" << spaceDim << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
3901   DataArrayInt *ret1=0;
3902   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3903   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3904   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3905   cellId=*ret1Safe->begin();
3906   return *ret0->begin();
3907 }
3908
3909 /*!
3910  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3911  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3912  * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3913  * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3914  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3915  * 
3916  * \a this is expected to be a mesh so that its space dimension is equal to its
3917  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3918  * Number of components of \a pts is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
3919  *
3920  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3921  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3922  *
3923  * \param [in] pts the list of points in which each tuple represents a point
3924  * \param [out] cellIds a newly allocated object that tells for each point in \a pts the first cell id in \a this that minimizes the distance.
3925  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3926  * \throw if number of components of \a pts is not equal to the space dimension.
3927  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3928  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3929  */
3930 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3931 {
3932   if(!pts)
3933     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3934   pts->checkAllocated();
3935   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3936   if(meshDim!=spaceDim-1)
3937     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3938   if(meshDim!=2 && meshDim!=1)
3939     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3940   if(pts->getNumberOfComponents()!=spaceDim)
3941     {
3942       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3943       throw INTERP_KERNEL::Exception(oss.str().c_str());
3944     }
3945   checkFullyDefined();
3946   int nbCells=getNumberOfCells();
3947   if(nbCells==0)
3948     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3949   int nbOfPts=pts->getNumberOfTuples();
3950   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3951   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3952   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3953   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3954   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3955   const double *bbox(bboxArr->begin());
3956   switch(spaceDim)
3957   {
3958     case 3:
3959       {
3960         BBTreeDst<3> myTree(bbox,0,0,nbCells);
3961         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3962           {
3963             double x=std::numeric_limits<double>::max();
3964             std::vector<int> elems;
3965             myTree.getMinDistanceOfMax(ptsPtr,x);
3966             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3967             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3968           }
3969         break;
3970       }
3971     case 2:
3972       {
3973         BBTreeDst<2> myTree(bbox,0,0,nbCells);
3974         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3975           {
3976             double x=std::numeric_limits<double>::max();
3977             std::vector<int> elems;
3978             myTree.getMinDistanceOfMax(ptsPtr,x);
3979             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3980             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3981           }
3982         break;
3983       }
3984     default:
3985       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3986   }
3987   cellIds=ret1.retn();
3988   return ret0.retn();
3989 }
3990
3991 /*!
3992  * \param [in] pt the start pointer (included) of the coordinates of the point
3993  * \param [in] cellIdsBg the start pointer (included) of cellIds
3994  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3995  * \param [in] nc nodal connectivity
3996  * \param [in] ncI nodal connectivity index
3997  * \param [in,out] ret0 the min distance between \a this and the external input point
3998  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3999  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4000  */
4001 void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId)
4002 {
4003   cellId=-1;
4004   ret0=std::numeric_limits<double>::max();
4005   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4006     {
4007       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4008       {
4009         case INTERP_KERNEL::NORM_TRI3:
4010           {
4011             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4012             if(tmp<ret0)
4013               { ret0=tmp; cellId=*zeCell; }
4014             break;
4015           }
4016         case INTERP_KERNEL::NORM_QUAD4:
4017         case INTERP_KERNEL::NORM_POLYGON:
4018           {
4019             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4020             if(tmp<ret0)
4021               { ret0=tmp; cellId=*zeCell; }
4022             break;
4023           }
4024         default:
4025           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4026       }
4027     }
4028 }
4029
4030 /*!
4031  * \param [in] pt the start pointer (included) of the coordinates of the point
4032  * \param [in] cellIdsBg the start pointer (included) of cellIds
4033  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4034  * \param [in] nc nodal connectivity
4035  * \param [in] ncI nodal connectivity index
4036  * \param [in,out] ret0 the min distance between \a this and the external input point
4037  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4038  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4039  */
4040 void MEDCouplingUMesh::DistanceToPoint2DCurveAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId)
4041 {
4042   cellId=-1;
4043   ret0=std::numeric_limits<double>::max();
4044   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4045     {
4046       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4047       {
4048         case INTERP_KERNEL::NORM_SEG2:
4049           {
4050             std::size_t uselessEntry=0;
4051             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4052             tmp=sqrt(tmp);
4053             if(tmp<ret0)
4054               { ret0=tmp; cellId=*zeCell; }
4055             break;
4056           }
4057         default:
4058           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4059       }
4060     }
4061 }
4062
4063 /*!
4064  * Finds cells in contact with a ball (i.e. a point with precision). 
4065  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4066  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4067  *
4068  * \warning This method is suitable if the caller intends to evaluate only one
4069  *          point, for more points getCellsContainingPoints() is recommended as it is
4070  *          faster. 
4071  *  \param [in] pos - array of coordinates of the ball central point.
4072  *  \param [in] eps - ball radius.
4073  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4074  *         if there are no such cells.
4075  *  \throw If the coordinates array is not set.
4076  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4077  */
4078 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4079 {
4080   std::vector<int> elts;
4081   getCellsContainingPoint(pos,eps,elts);
4082   if(elts.empty())
4083     return -1;
4084   return elts.front();
4085 }
4086
4087 /*!
4088  * Finds cells in contact with a ball (i.e. a point with precision).
4089  * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4090  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4091  * \warning This method is suitable if the caller intends to evaluate only one
4092  *          point, for more points getCellsContainingPoints() is recommended as it is
4093  *          faster. 
4094  *  \param [in] pos - array of coordinates of the ball central point.
4095  *  \param [in] eps - ball radius.
4096  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4097  *         before inserting ids.
4098  *  \throw If the coordinates array is not set.
4099  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4100  *
4101  *  \if ENABLE_EXAMPLES
4102  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4103  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4104  *  \endif
4105  */
4106 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4107 {
4108   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4109   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4110   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4111 }
4112
4113 /// @cond INTERNAL
4114
4115 namespace ParaMEDMEM
4116 {
4117   template<const int SPACEDIMM>
4118   class DummyClsMCUG
4119   {
4120   public:
4121     static const int MY_SPACEDIM=SPACEDIMM;
4122     static const int MY_MESHDIM=8;
4123     typedef int MyConnType;
4124     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4125     // begin
4126     // useless, but for windows compilation ...
4127     const double* getCoordinatesPtr() const { return 0; }
4128     const int* getConnectivityPtr() const { return 0; }
4129     const int* getConnectivityIndexPtr() const { return 0; }
4130     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4131     // end
4132   };
4133
4134   /*!
4135    * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4136    */
4137   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map<INTERP_KERNEL::Node *,int>& m)
4138   {
4139     INTERP_KERNEL::Edge *ret=0;
4140     INTERP_KERNEL::Node *n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),*n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1]));
4141     m[n0]=bg[0]; m[n1]=bg[1];
4142     switch(typ)
4143     {
4144       case INTERP_KERNEL::NORM_SEG2:
4145         {
4146           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4147           break;
4148         }
4149       case INTERP_KERNEL::NORM_SEG3:
4150         {
4151           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4152           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4153           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4154           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4155           bool colinearity(inters.areColinears());
4156           delete e1; delete e2;
4157           if(colinearity)
4158             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4159           else
4160             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4161           break;
4162         }
4163       default:
4164         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4165     }
4166     return ret;
4167   }
4168
4169   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4170   {
4171     INTERP_KERNEL::Edge *ret=0;
4172     switch(typ)
4173     {
4174       case INTERP_KERNEL::NORM_SEG2:
4175         {
4176           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4177           break;
4178         }
4179       case INTERP_KERNEL::NORM_SEG3:
4180         {
4181           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4182           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4183           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4184           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4185           bool colinearity=inters.areColinears();
4186           delete e1; delete e2;
4187           if(colinearity)
4188             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4189           else
4190             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4191           mapp2[bg[2]].second=false;
4192           break;
4193         }
4194       default:
4195         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4196     }
4197     return ret;
4198   }
4199
4200   /*!
4201    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4202    * the global mesh 'mDesc'.
4203    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4204    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4205    */
4206   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4207                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4208   {
4209     mapp.clear();
4210     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.
4211     const double *coo=mDesc->getCoords()->getConstPointer();
4212     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4213     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4214     std::set<int> s;
4215     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4216       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4217     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4218       {
4219         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4220         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4221       }
4222     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4223     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4224       {
4225         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4226         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4227       }
4228     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4229       {
4230         if((*it2).second.second)
4231           mapp[(*it2).second.first]=(*it2).first;
4232         ((*it2).second.first)->decrRef();
4233       }
4234     return ret;
4235   }
4236
4237   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4238   {
4239     if(nodeId>=offset2)
4240       {
4241         int locId=nodeId-offset2;
4242         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4243       }
4244     if(nodeId>=offset1)
4245       {
4246         int locId=nodeId-offset1;
4247         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4248       }
4249     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4250   }
4251
4252   /**
4253    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4254    */
4255   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4256                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4257                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4258   {
4259     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4260       {
4261         int eltId1=abs(*desc1)-1;
4262         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4263           {
4264             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4265             if(it==mappRev.end())
4266               {
4267                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4268                 mapp[node]=*it1;
4269                 mappRev[*it1]=node;
4270               }
4271           }
4272       }
4273   }
4274 }
4275
4276 /// @endcond
4277
4278 template<int SPACEDIM>
4279 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4280                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4281 {
4282   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4283   int *eltsIndexPtr(eltsIndex->getPointer());
4284   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4285   const double *bbox(bboxArr->begin());
4286   int nbOfCells=getNumberOfCells();
4287   const int *conn=_nodal_connec->getConstPointer();
4288   const int *connI=_nodal_connec_index->getConstPointer();
4289   double bb[2*SPACEDIM];
4290   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4291   for(int i=0;i<nbOfPoints;i++)
4292     {
4293       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4294       for(int j=0;j<SPACEDIM;j++)
4295         {
4296           bb[2*j]=pos[SPACEDIM*i+j];
4297           bb[2*j+1]=pos[SPACEDIM*i+j];
4298         }
4299       std::vector<int> candidates;
4300       myTree.getIntersectingElems(bb,candidates);
4301       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4302         {
4303           int sz(connI[(*iter)+1]-connI[*iter]-1);
4304           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4305           bool status(false);
4306           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4307             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4308           else
4309             {
4310               if(SPACEDIM!=2)
4311                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4312               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4313               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4314               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4315               INTERP_KERNEL::QuadraticPolygon *pol(0);
4316               for(int j=0;j<sz;j++)
4317                 {
4318                   int nodeId(conn[connI[*iter]+1+j]);
4319                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4320                 }
4321               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4322                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4323               else
4324                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4325               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4326               double a(0.),b(0.),c(0.);
4327               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4328               status=pol->isInOrOut2(n);
4329               delete pol; n->decrRef();
4330             }
4331           if(status)
4332             {
4333               eltsIndexPtr[i+1]++;
4334               elts->pushBackSilent(*iter);
4335             }
4336         }
4337     }
4338 }
4339 /*!
4340  * Finds cells in contact with several balls (i.e. points with precision).
4341  * This method is an extension of getCellContainingPoint() and
4342  * getCellsContainingPoint() for the case of multiple points.
4343  * 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.
4344  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4345  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4346  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4347  *         this->getSpaceDimension() * \a nbOfPoints 
4348  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4349  *  \param [in] eps - radius of balls (i.e. the precision).
4350  *  \param [out] elts - vector returning ids of found cells.
4351  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4352  *         dividing cell ids in \a elts into groups each referring to one
4353  *         point. Its every element (except the last one) is an index pointing to the
4354  *         first id of a group of cells. For example cells in contact with the *i*-th
4355  *         point are described by following range of indices:
4356  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4357  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4358  *         Number of cells in contact with the *i*-th point is
4359  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4360  *  \throw If the coordinates array is not set.
4361  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4362  *
4363  *  \if ENABLE_EXAMPLES
4364  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4365  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4366  *  \endif
4367  */
4368 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4369                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4370 {
4371   int spaceDim=getSpaceDimension();
4372   int mDim=getMeshDimension();
4373   if(spaceDim==3)
4374     {
4375       if(mDim==3)
4376         {
4377           const double *coords=_coords->getConstPointer();
4378           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4379         }
4380       /*else if(mDim==2)
4381         {
4382
4383         }*/
4384       else
4385         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4386     }
4387   else if(spaceDim==2)
4388     {
4389       if(mDim==2)
4390         {
4391           const double *coords=_coords->getConstPointer();
4392           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4393         }
4394       else
4395         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4396     }
4397   else if(spaceDim==1)
4398     {
4399       if(mDim==1)
4400         {
4401           const double *coords=_coords->getConstPointer();
4402           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4403         }
4404       else
4405         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4406     }
4407   else
4408     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4409 }
4410
4411 /*!
4412  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4413  * least two its edges intersect each other anywhere except their extremities. An
4414  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4415  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4416  *         cleared before filling in.
4417  *  \param [in] eps - precision.
4418  *  \throw If \a this->getMeshDimension() != 2.
4419  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4420  */
4421 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4422 {
4423   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4424   if(getMeshDimension()!=2)
4425     throw INTERP_KERNEL::Exception(msg);
4426   int spaceDim=getSpaceDimension();
4427   if(spaceDim!=2 && spaceDim!=3)
4428     throw INTERP_KERNEL::Exception(msg);
4429   const int *conn=_nodal_connec->getConstPointer();
4430   const int *connI=_nodal_connec_index->getConstPointer();
4431   int nbOfCells=getNumberOfCells();
4432   std::vector<double> cell2DinS2;
4433   for(int i=0;i<nbOfCells;i++)
4434     {
4435       int offset=connI[i];
4436       int nbOfNodesForCell=connI[i+1]-offset-1;
4437       if(nbOfNodesForCell<=3)
4438         continue;
4439       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4440       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4441       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4442         cells.push_back(i);
4443       cell2DinS2.clear();
4444     }
4445 }
4446
4447 /*!
4448  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4449  *
4450  * 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.
4451  * 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.
4452  * 
4453  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4454  * This convex envelop is computed using Jarvis march algorithm.
4455  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4456  * 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)
4457  * 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.
4458  *
4459  * \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.
4460  * \sa MEDCouplingUMesh::colinearize2D
4461  */
4462 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4463 {
4464   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4465     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4466   checkFullyDefined();
4467   const double *coords=getCoords()->getConstPointer();
4468   int nbOfCells=getNumberOfCells();
4469   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4470   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4472   int *workIndexOut=nodalConnecIndexOut->getPointer();
4473   *workIndexOut=0;
4474   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4475   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4476   std::set<INTERP_KERNEL::NormalizedCellType> types;
4477   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4478   isChanged->alloc(0,1);
4479   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4480     {
4481       int pos=nodalConnecOut->getNumberOfTuples();
4482       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4483         isChanged->pushBackSilent(i);
4484       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4485       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4486     }
4487   if(isChanged->empty())
4488     return 0;
4489   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4490   _types=types;
4491   return isChanged.retn();
4492 }
4493
4494 /*!
4495  * This method is \b NOT const because it can modify \a this.
4496  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4497  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4498  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4499  * \b 1 for translation and rotation around point of 'mesh1D'.
4500  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4501  */
4502 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4503 {
4504   checkFullyDefined();
4505   mesh1D->checkFullyDefined();
4506   if(!mesh1D->isContiguous1D())
4507     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4508   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4509     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4510   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4511     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4512   if(mesh1D->getMeshDimension()!=1)
4513     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4514   bool isQuad=false;
4515   if(isPresenceOfQuadratic())
4516     {
4517       if(mesh1D->isFullyQuadratic())
4518         isQuad=true;
4519       else
4520         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4521     }
4522   zipCoords();
4523   int oldNbOfNodes=getNumberOfNodes();
4524   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4525   switch(policy)
4526   {
4527     case 0:
4528       {
4529         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4530         break;
4531       }
4532     case 1:
4533       {
4534         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4535         break;
4536       }
4537     default:
4538       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4539   }
4540   setCoords(newCoords);
4541   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4542   updateTime();
4543   return ret.retn();
4544 }
4545
4546 /*!
4547  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4548  * If it is not the case an exception will be thrown.
4549  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4550  * intersection of plane defined by ('origin','vec').
4551  * This method has one in/out parameter : 'cut3DCurve'.
4552  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4553  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4554  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4555  * This method will throw an exception if \a this contains a non linear segment.
4556  */
4557 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4558 {
4559   checkFullyDefined();
4560   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4561     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4562   int ncells=getNumberOfCells();
4563   int nnodes=getNumberOfNodes();
4564   double vec2[3],vec3[3],vec4[3];
4565   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4566   if(normm<1e-6)
4567     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4568   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4569   const int *conn=_nodal_connec->getConstPointer();
4570   const int *connI=_nodal_connec_index->getConstPointer();
4571   const double *coo=_coords->getConstPointer();
4572   std::vector<double> addCoo;
4573   for(int i=0;i<ncells;i++)
4574     {
4575       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4576         {
4577           if(cut3DCurve[i]==-2)
4578             {
4579               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4580               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];
4581               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4582               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4583               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4584                 {
4585                   const double *st2=coo+3*st;
4586                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4587                   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]));
4588                   if(pos>eps && pos<1-eps)
4589                     {
4590                       int nNode=((int)addCoo.size())/3;
4591                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4592                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4593                       cut3DCurve[i]=nnodes+nNode;
4594                     }
4595                 }
4596             }
4597         }
4598       else
4599         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4600     }
4601   if(!addCoo.empty())
4602     {
4603       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4604       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4605       coo2->alloc(newNbOfNodes,3);
4606       double *tmp=coo2->getPointer();
4607       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4608       std::copy(addCoo.begin(),addCoo.end(),tmp);
4609       DataArrayDouble::SetArrayIn(coo2,_coords);
4610     }
4611 }
4612
4613 /*!
4614  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4615  * \param mesh1D is the input 1D mesh used for translation computation.
4616  * \return newCoords new coords filled by this method. 
4617  */
4618 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4619 {
4620   int oldNbOfNodes=getNumberOfNodes();
4621   int nbOf1DCells=mesh1D->getNumberOfCells();
4622   int spaceDim=getSpaceDimension();
4623   DataArrayDouble *ret=DataArrayDouble::New();
4624   std::vector<bool> isQuads;
4625   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4626   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4627   double *retPtr=ret->getPointer();
4628   const double *coords=getCoords()->getConstPointer();
4629   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4630   std::vector<int> v;
4631   std::vector<double> c;
4632   double vec[3];
4633   v.reserve(3);
4634   c.reserve(6);
4635   for(int i=0;i<nbOf1DCells;i++)
4636     {
4637       v.resize(0);
4638       mesh1D->getNodeIdsOfCell(i,v);
4639       c.resize(0);
4640       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4641       mesh1D->getCoordinatesOfNode(v[0],c);
4642       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4643       for(int j=0;j<oldNbOfNodes;j++)
4644         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4645       if(isQuad)
4646         {
4647           c.resize(0);
4648           mesh1D->getCoordinatesOfNode(v[1],c);
4649           mesh1D->getCoordinatesOfNode(v[0],c);
4650           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4651           for(int j=0;j<oldNbOfNodes;j++)
4652             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4653         }
4654     }
4655   ret->copyStringInfoFrom(*getCoords());
4656   return ret;
4657 }
4658
4659 /*!
4660  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4661  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4662  * \return newCoords new coords filled by this method. 
4663  */
4664 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4665 {
4666   if(mesh1D->getSpaceDimension()==2)
4667     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4668   if(mesh1D->getSpaceDimension()==3)
4669     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4670   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4671 }
4672
4673 /*!
4674  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4675  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4676  * \return newCoords new coords filled by this method. 
4677  */
4678 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4679 {
4680   if(isQuad)
4681     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4682   int oldNbOfNodes=getNumberOfNodes();
4683   int nbOf1DCells=mesh1D->getNumberOfCells();
4684   if(nbOf1DCells<2)
4685     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4686   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4687   int nbOfLevsInVec=nbOf1DCells+1;
4688   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4689   double *retPtr=ret->getPointer();
4690   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4691   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4692   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4693   tmp->setCoords(tmp2);
4694   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4695   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4696   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4697   for(int i=1;i<nbOfLevsInVec;i++)
4698     {
4699       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4700       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4701       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4702       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4703       tmp->translate(vec);
4704       double tmp3[2],radius,alpha,alpha0;
4705       const double *p0=i+1<nbOfLevsInVec?begin:third;
4706       const double *p1=i+1<nbOfLevsInVec?end:begin;
4707       const double *p2=i+1<nbOfLevsInVec?third:end;
4708       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4709       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]);
4710       double angle=acos(cosangle/(radius*radius));
4711       tmp->rotate(end,0,angle);
4712       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4713     }
4714   return ret.retn();
4715 }
4716
4717 /*!
4718  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4719  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4720  * \return newCoords new coords filled by this method. 
4721  */
4722 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4723 {
4724   if(isQuad)
4725     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4726   int oldNbOfNodes=getNumberOfNodes();
4727   int nbOf1DCells=mesh1D->getNumberOfCells();
4728   if(nbOf1DCells<2)
4729     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4730   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4731   int nbOfLevsInVec=nbOf1DCells+1;
4732   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4733   double *retPtr=ret->getPointer();
4734   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4735   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4736   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4737   tmp->setCoords(tmp2);
4738   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4739   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4740   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4741   for(int i=1;i<nbOfLevsInVec;i++)
4742     {
4743       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4744       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4745       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4746       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4747       tmp->translate(vec);
4748       double tmp3[2],radius,alpha,alpha0;
4749       const double *p0=i+1<nbOfLevsInVec?begin:third;
4750       const double *p1=i+1<nbOfLevsInVec?end:begin;
4751       const double *p2=i+1<nbOfLevsInVec?third:end;
4752       double vecPlane[3]={
4753         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4754         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4755         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4756       };
4757       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4758       if(norm>1.e-7)
4759         {
4760           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4761           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4762           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4763           double s2=norm2;
4764           double c2=cos(asin(s2));
4765           double m[3][3]={
4766             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4767             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4768             {-vec2[1]*s2, vec2[0]*s2, c2}
4769           };
4770           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]};
4771           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]};
4772           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]};
4773           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4774           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]);
4775           double angle=acos(cosangle/(radius*radius));
4776           tmp->rotate(end,vecPlane,angle);
4777         }
4778       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4779     }
4780   return ret.retn();
4781 }
4782
4783 /*!
4784  * This method is private because not easy to use for end user. This method is const contrary to
4785  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4786  * the coords sorted slice by slice.
4787  * \param isQuad specifies presence of quadratic cells.
4788  */
4789 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4790 {
4791   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4792   int nbOf2DCells=getNumberOfCells();
4793   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4794   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4795   const int *conn=_nodal_connec->getConstPointer();
4796   const int *connI=_nodal_connec_index->getConstPointer();
4797   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4798   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4799   newConnI->alloc(nbOf3DCells+1,1);
4800   int *newConnIPtr=newConnI->getPointer();
4801   *newConnIPtr++=0;
4802   std::vector<int> newc;
4803   for(int j=0;j<nbOf2DCells;j++)
4804     {
4805       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4806       *newConnIPtr++=(int)newc.size();
4807     }
4808   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4809   int *newConnPtr=newConn->getPointer();
4810   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4811   newConnIPtr=newConnI->getPointer();
4812   for(int iz=0;iz<nbOf1DCells;iz++)
4813     {
4814       if(iz!=0)
4815         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4816       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4817         {
4818           int icell=(int)(iter-newc.begin());
4819           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4820             {
4821               if(*iter!=-1)
4822                 *newConnPtr=(*iter)+iz*deltaPerLev;
4823               else
4824                 *newConnPtr=-1;
4825             }
4826           else
4827             *newConnPtr=(*iter);
4828         }
4829     }
4830   ret->setConnectivity(newConn,newConnI,true);
4831   ret->setCoords(getCoords());
4832   return ret;
4833 }
4834
4835 /*!
4836  * Checks if \a this mesh is constituted by only quadratic cells.
4837  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4838  *  \throw If the coordinates array is not set.
4839  *  \throw If the nodal connectivity of cells is not defined.
4840  */
4841 bool MEDCouplingUMesh::isFullyQuadratic() const
4842 {
4843   checkFullyDefined();
4844   bool ret=true;
4845   int nbOfCells=getNumberOfCells();
4846   for(int i=0;i<nbOfCells && ret;i++)
4847     {
4848       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4849       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4850       ret=cm.isQuadratic();
4851     }
4852   return ret;
4853 }
4854
4855 /*!
4856  * Checks if \a this mesh includes any quadratic cell.
4857  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4858  *  \throw If the coordinates array is not set.
4859  *  \throw If the nodal connectivity of cells is not defined.
4860  */
4861 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4862 {
4863   checkFullyDefined();
4864   bool ret=false;
4865   int nbOfCells=getNumberOfCells();
4866   for(int i=0;i<nbOfCells && !ret;i++)
4867     {
4868       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4869       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4870       ret=cm.isQuadratic();
4871     }
4872   return ret;
4873 }
4874
4875 /*!
4876  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4877  * this mesh, it remains unchanged.
4878  *  \throw If the coordinates array is not set.
4879  *  \throw If the nodal connectivity of cells is not defined.
4880  */
4881 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4882 {
4883   checkFullyDefined();
4884   int nbOfCells=getNumberOfCells();
4885   int delta=0;
4886   const int *iciptr=_nodal_connec_index->getConstPointer();
4887   for(int i=0;i<nbOfCells;i++)
4888     {
4889       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4890       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4891       if(cm.isQuadratic())
4892         {
4893           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4894           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4895           if(!cml.isDynamic())
4896             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4897           else
4898             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4899         }
4900     }
4901   if(delta==0)
4902     return ;
4903   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4904   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4905   const int *icptr=_nodal_connec->getConstPointer();
4906   newConn->alloc(getMeshLength()-delta,1);
4907   newConnI->alloc(nbOfCells+1,1);
4908   int *ocptr=newConn->getPointer();
4909   int *ociptr=newConnI->getPointer();
4910   *ociptr=0;
4911   _types.clear();
4912   for(int i=0;i<nbOfCells;i++,ociptr++)
4913     {
4914       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4915       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4916       if(!cm.isQuadratic())
4917         {
4918           _types.insert(type);
4919           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4920           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4921         }
4922       else
4923         {
4924           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4925           _types.insert(typel);
4926           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4927           int newNbOfNodes=cml.getNumberOfNodes();
4928           if(cml.isDynamic())
4929             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4930           *ocptr++=(int)typel;
4931           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4932           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4933         }
4934     }
4935   setConnectivity(newConn,newConnI,false);
4936 }
4937
4938 /*!
4939  * This method converts all linear cell in \a this to quadratic one.
4940  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4941  * 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)
4942  * 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.
4943  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4944  * end of the existing coordinates.
4945  * 
4946  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4947  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4948  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4949  * 
4950  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4951  *
4952  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4953  */
4954 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4955 {
4956   DataArrayInt *conn=0,*connI=0;
4957   DataArrayDouble *coords=0;
4958   std::set<INTERP_KERNEL::NormalizedCellType> types;
4959   checkFullyDefined();
4960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4961   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4962   int meshDim=getMeshDimension();
4963   switch(conversionType)
4964   {
4965     case 0:
4966       switch(meshDim)
4967       {
4968         case 1:
4969           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4970           connSafe=conn; connISafe=connI; coordsSafe=coords;
4971           break;
4972         case 2:
4973           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4974           connSafe=conn; connISafe=connI; coordsSafe=coords;
4975           break;
4976         case 3:
4977           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4978           connSafe=conn; connISafe=connI; coordsSafe=coords;
4979           break;
4980         default:
4981           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4982       }
4983       break;
4984         case 1:
4985           {
4986             switch(meshDim)
4987             {
4988               case 1:
4989                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4990                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4991                 break;
4992               case 2:
4993                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4994                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4995                 break;
4996               case 3:
4997                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4998                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4999                 break;
5000               default:
5001                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5002             }
5003             break;
5004           }
5005         default:
5006           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5007   }
5008   setConnectivity(connSafe,connISafe,false);
5009   _types=types;
5010   setCoords(coordsSafe);
5011   return ret.retn();
5012 }
5013
5014 /*!
5015  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5016  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5017  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5018  */
5019 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5020 {
5021   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5022   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5023   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5024   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5025   int nbOfCells=getNumberOfCells();
5026   int nbOfNodes=getNumberOfNodes();
5027   const int *cPtr=_nodal_connec->getConstPointer();
5028   const int *icPtr=_nodal_connec_index->getConstPointer();
5029   int lastVal=0,offset=nbOfNodes;
5030   for(int i=0;i<nbOfCells;i++,icPtr++)
5031     {
5032       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5033       if(type==INTERP_KERNEL::NORM_SEG2)
5034         {
5035           types.insert(INTERP_KERNEL::NORM_SEG3);
5036           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5037           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5038           newConn->pushBackSilent(offset++);
5039           lastVal+=4;
5040           newConnI->pushBackSilent(lastVal);
5041           ret->pushBackSilent(i);
5042         }
5043       else
5044         {
5045           types.insert(type);
5046           lastVal+=(icPtr[1]-icPtr[0]);
5047           newConnI->pushBackSilent(lastVal);
5048           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5049         }
5050     }
5051   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5052   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5053   return ret.retn();
5054 }
5055
5056 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
5057 {
5058   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5059   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5060   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5061   //
5062   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5063   DataArrayInt *conn1D=0,*conn1DI=0;
5064   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5065   DataArrayDouble *coordsTmp=0;
5066   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5067   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5068   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5069   const int *c1DPtr=conn1D->begin();
5070   const int *c1DIPtr=conn1DI->begin();
5071   int nbOfCells=getNumberOfCells();
5072   const int *cPtr=_nodal_connec->getConstPointer();
5073   const int *icPtr=_nodal_connec_index->getConstPointer();
5074   int lastVal=0;
5075   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5076     {
5077       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5078       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5079       if(!cm.isQuadratic())
5080         {
5081           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5082           types.insert(typ2); newConn->pushBackSilent(typ2);
5083           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5084           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5085             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5086           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5087           newConnI->pushBackSilent(lastVal);
5088           ret->pushBackSilent(i);
5089         }
5090       else
5091         {
5092           types.insert(typ);
5093           lastVal+=(icPtr[1]-icPtr[0]);
5094           newConnI->pushBackSilent(lastVal);
5095           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5096         }
5097     }
5098   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5099   return ret.retn();
5100 }
5101
5102 /*!
5103  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5104  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5105  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5106  */
5107 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5108 {
5109   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5110   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5111   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5112 }
5113
5114 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5115 {
5116   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5117   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5118   //
5119   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5120   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5121   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5122   //
5123   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5124   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5125   DataArrayInt *conn1D=0,*conn1DI=0;
5126   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5127   DataArrayDouble *coordsTmp=0;
5128   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5129   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5130   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5131   const int *c1DPtr=conn1D->begin();
5132   const int *c1DIPtr=conn1DI->begin();
5133   int nbOfCells=getNumberOfCells();
5134   const int *cPtr=_nodal_connec->getConstPointer();
5135   const int *icPtr=_nodal_connec_index->getConstPointer();
5136   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5137   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5138     {
5139       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5140       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5141       if(!cm.isQuadratic())
5142         {
5143           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5144           types.insert(typ2); newConn->pushBackSilent(typ2);
5145           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5146           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5147             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5148           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5149           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5150           newConnI->pushBackSilent(lastVal);
5151           ret->pushBackSilent(i);
5152         }
5153       else
5154         {
5155           types.insert(typ);
5156           lastVal+=(icPtr[1]-icPtr[0]);
5157           newConnI->pushBackSilent(lastVal);
5158           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5159         }
5160     }
5161   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5162   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5163   return ret.retn();
5164 }
5165
5166 /*!
5167  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5168  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5169  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5170  */
5171 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5172 {
5173   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5174   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5175   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5176 }
5177
5178 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5179 {
5180   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5181   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5182   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5183   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5184   //
5185   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5186   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5187   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5188   //
5189   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5190   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5191   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5192   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5193   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5194   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5195   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5196   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5197   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5198   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5199   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5200   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5201   int nbOfCells=getNumberOfCells();
5202   const int *cPtr=_nodal_connec->getConstPointer();
5203   const int *icPtr=_nodal_connec_index->getConstPointer();
5204   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5205   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5206     {
5207       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5208       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5209       if(!cm.isQuadratic())
5210         {
5211           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5212           if(typ2==INTERP_KERNEL::NORM_ERROR)
5213             {
5214               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5215               throw INTERP_KERNEL::Exception(oss.str().c_str());
5216             }
5217           types.insert(typ2); newConn->pushBackSilent(typ2);
5218           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5219           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5220             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5221           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5222             {
5223               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5224               int tmpPos=newConn->getNumberOfTuples();
5225               newConn->pushBackSilent(nodeId2);
5226               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5227             }
5228           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5229           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5230           newConnI->pushBackSilent(lastVal);
5231           ret->pushBackSilent(i);
5232         }
5233       else
5234         {
5235           types.insert(typ);
5236           lastVal+=(icPtr[1]-icPtr[0]);
5237           newConnI->pushBackSilent(lastVal);
5238           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5239         }
5240     }
5241   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5242   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5243   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5244   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5245   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5246   int *c=newConn->getPointer();
5247   const int *cI(newConnI->begin());
5248   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5249     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5250   offset=coordsTmp2Safe->getNumberOfTuples();
5251   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5252     c[cI[(*elt)+1]-1]+=offset;
5253   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5254   return ret.retn();
5255 }
5256
5257 /*!
5258  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5259  * so that the number of cells remains the same. Quadratic faces are converted to
5260  * polygons. This method works only for 2D meshes in
5261  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5262  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5263  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5264  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5265  *         a polylinized edge constituting the input polygon.
5266  *  \throw If the coordinates array is not set.
5267  *  \throw If the nodal connectivity of cells is not defined.
5268  *  \throw If \a this->getMeshDimension() != 2.
5269  *  \throw If \a this->getSpaceDimension() != 2.
5270  */
5271 void MEDCouplingUMesh::tessellate2D(double eps)
5272 {
5273   checkFullyDefined();
5274   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5275     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5276   double epsa=fabs(eps);
5277   if(epsa<std::numeric_limits<double>::min())
5278     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 !");
5279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5280   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5281   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5282   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5283   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5284   revDesc1=0; revDescIndx1=0;
5285   mDesc->tessellate2DCurve(eps);
5286   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5287   setCoords(mDesc->getCoords());
5288 }
5289
5290 /*!
5291  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5292  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5293  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5294  *         a sub-divided edge.
5295  *  \throw If the coordinates array is not set.
5296  *  \throw If the nodal connectivity of cells is not defined.
5297  *  \throw If \a this->getMeshDimension() != 1.
5298  *  \throw If \a this->getSpaceDimension() != 2.
5299  */
5300 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5301 {
5302   checkFullyDefined();
5303   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5304     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5305   double epsa=fabs(eps);
5306   if(epsa<std::numeric_limits<double>::min())
5307     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 !");
5308   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5309   int nbCells=getNumberOfCells();
5310   int nbNodes=getNumberOfNodes();
5311   const int *conn=_nodal_connec->getConstPointer();
5312   const int *connI=_nodal_connec_index->getConstPointer();
5313   const double *coords=_coords->getConstPointer();
5314   std::vector<double> addCoo;
5315   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5316   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5317   newConnI->alloc(nbCells+1,1);
5318   int *newConnIPtr=newConnI->getPointer();
5319   *newConnIPtr=0;
5320   int tmp1[3];
5321   INTERP_KERNEL::Node *tmp2[3];
5322   std::set<INTERP_KERNEL::NormalizedCellType> types;
5323   for(int i=0;i<nbCells;i++,newConnIPtr++)
5324     {
5325       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5326       if(cm.isQuadratic())
5327         {//assert(connI[i+1]-connI[i]-1==3)
5328           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5329           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5330           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5331           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5332           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5333           if(eac)
5334             {
5335               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5336               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5337               delete eac;
5338               newConnIPtr[1]=(int)newConn.size();
5339             }
5340           else
5341             {
5342               types.insert(INTERP_KERNEL::NORM_SEG2);
5343               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5344               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5345               newConnIPtr[1]=newConnIPtr[0]+3;
5346             }
5347         }
5348       else
5349         {
5350           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5351           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5352           newConnIPtr[1]=newConnIPtr[0]+3;
5353         }
5354     }
5355   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5356     return ;
5357   _types=types;
5358   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5360   newConnArr->alloc((int)newConn.size(),1);
5361   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5362   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5363   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5364   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5365   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5366   std::copy(addCoo.begin(),addCoo.end(),work);
5367   DataArrayDouble::SetArrayIn(newCoords,_coords);
5368   updateTime();
5369 }
5370
5371 /*!
5372  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5373  * In addition, returns an array mapping new cells to old ones. <br>
5374  * This method typically increases the number of cells in \a this mesh
5375  * but the number of nodes remains \b unchanged.
5376  * That's why the 3D splitting policies
5377  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5378  *  \param [in] policy - specifies a pattern used for splitting.
5379  * The semantic of \a policy is:
5380  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5381  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5382  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5383  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5384  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5385  *          an id of old cell producing it. The caller is to delete this array using
5386  *         decrRef() as it is no more needed. 
5387  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5388  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5389  *          and \a this->getMeshDimension() != 3. 
5390  *  \throw If \a policy is not one of the four discussed above.
5391  *  \throw If the nodal connectivity of cells is not defined.
5392  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5393  */
5394 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5395 {
5396   switch(policy)
5397   {
5398     case 0:
5399       return simplexizePol0();
5400     case 1:
5401       return simplexizePol1();
5402     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5403         return simplexizePlanarFace5();
5404     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5405         return simplexizePlanarFace6();
5406     default:
5407       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)");
5408   }
5409 }
5410
5411 /*!
5412  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5413  * - 1D: INTERP_KERNEL::NORM_SEG2
5414  * - 2D: INTERP_KERNEL::NORM_TRI3
5415  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5416  *
5417  * This method is useful for users that need to use P1 field services as
5418  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5419  * All these methods need mesh support containing only simplex cells.
5420  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5421  *  \throw If the coordinates array is not set.
5422  *  \throw If the nodal connectivity of cells is not defined.
5423  *  \throw If \a this->getMeshDimension() < 1.
5424  */
5425 bool MEDCouplingUMesh::areOnlySimplexCells() const
5426 {
5427   checkFullyDefined();
5428   int mdim=getMeshDimension();
5429   if(mdim<1 || mdim>3)
5430     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5431   int nbCells=getNumberOfCells();
5432   const int *conn=_nodal_connec->getConstPointer();
5433   const int *connI=_nodal_connec_index->getConstPointer();
5434   for(int i=0;i<nbCells;i++)
5435     {
5436       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5437       if(!cm.isSimplex())
5438         return false;
5439     }
5440   return true;
5441 }
5442
5443 /*!
5444  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5445  */
5446 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5447 {
5448   checkConnectivityFullyDefined();
5449   if(getMeshDimension()!=2)
5450     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5451   int nbOfCells=getNumberOfCells();
5452   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5453   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5454   ret->alloc(nbOfCells+nbOfCutCells,1);
5455   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5456   int *retPt=ret->getPointer();
5457   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5458   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5459   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5460   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5461   int *pt=newConn->getPointer();
5462   int *ptI=newConnI->getPointer();
5463   ptI[0]=0;
5464   const int *oldc=_nodal_connec->getConstPointer();
5465   const int *ci=_nodal_connec_index->getConstPointer();
5466   for(int i=0;i<nbOfCells;i++,ci++)
5467     {
5468       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5469         {
5470           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5471             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5472           pt=std::copy(tmp,tmp+8,pt);
5473           ptI[1]=ptI[0]+4;
5474           ptI[2]=ptI[0]+8;
5475           *retPt++=i;
5476           *retPt++=i;
5477           ptI+=2;
5478         }
5479       else
5480         {
5481           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5482           ptI[1]=ptI[0]+ci[1]-ci[0];
5483           ptI++;
5484           *retPt++=i;
5485         }
5486     }
5487   _nodal_connec->decrRef();
5488   _nodal_connec=newConn.retn();
5489   _nodal_connec_index->decrRef();
5490   _nodal_connec_index=newConnI.retn();
5491   computeTypes();
5492   updateTime();
5493   return ret.retn();
5494 }
5495
5496 /*!
5497  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5498  */
5499 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5500 {
5501   checkConnectivityFullyDefined();
5502   if(getMeshDimension()!=2)
5503     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5504   int nbOfCells=getNumberOfCells();
5505   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5506   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5507   ret->alloc(nbOfCells+nbOfCutCells,1);
5508   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5509   int *retPt=ret->getPointer();
5510   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5511   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5512   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5513   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5514   int *pt=newConn->getPointer();
5515   int *ptI=newConnI->getPointer();
5516   ptI[0]=0;
5517   const int *oldc=_nodal_connec->getConstPointer();
5518   const int *ci=_nodal_connec_index->getConstPointer();
5519   for(int i=0;i<nbOfCells;i++,ci++)
5520     {
5521       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5522         {
5523           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5524             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5525           pt=std::copy(tmp,tmp+8,pt);
5526           ptI[1]=ptI[0]+4;
5527           ptI[2]=ptI[0]+8;
5528           *retPt++=i;
5529           *retPt++=i;
5530           ptI+=2;
5531         }
5532       else
5533         {
5534           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5535           ptI[1]=ptI[0]+ci[1]-ci[0];
5536           ptI++;
5537           *retPt++=i;
5538         }
5539     }
5540   _nodal_connec->decrRef();
5541   _nodal_connec=newConn.retn();
5542   _nodal_connec_index->decrRef();
5543   _nodal_connec_index=newConnI.retn();
5544   computeTypes();
5545   updateTime();
5546   return ret.retn();
5547 }
5548
5549 /*!
5550  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5551  */
5552 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5553 {
5554   checkConnectivityFullyDefined();
5555   if(getMeshDimension()!=3)
5556     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5557   int nbOfCells=getNumberOfCells();
5558   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5559   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5560   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5561   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5562   int *retPt=ret->getPointer();
5563   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5564   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5565   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5566   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5567   int *pt=newConn->getPointer();
5568   int *ptI=newConnI->getPointer();
5569   ptI[0]=0;
5570   const int *oldc=_nodal_connec->getConstPointer();
5571   const int *ci=_nodal_connec_index->getConstPointer();
5572   for(int i=0;i<nbOfCells;i++,ci++)
5573     {
5574       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5575         {
5576           for(int j=0;j<5;j++,pt+=5,ptI++)
5577             {
5578               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5579               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];
5580               *retPt++=i;
5581               ptI[1]=ptI[0]+5;
5582             }
5583         }
5584       else
5585         {
5586           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5587           ptI[1]=ptI[0]+ci[1]-ci[0];
5588           ptI++;
5589           *retPt++=i;
5590         }
5591     }
5592   _nodal_connec->decrRef();
5593   _nodal_connec=newConn.retn();
5594   _nodal_connec_index->decrRef();
5595   _nodal_connec_index=newConnI.retn();
5596   computeTypes();
5597   updateTime();
5598   return ret.retn();
5599 }
5600
5601 /*!
5602  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5603  */
5604 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5605 {
5606   checkConnectivityFullyDefined();
5607   if(getMeshDimension()!=3)
5608     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5609   int nbOfCells=getNumberOfCells();
5610   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5611   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5612   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5613   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5614   int *retPt=ret->getPointer();
5615   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5616   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5617   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5618   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5619   int *pt=newConn->getPointer();
5620   int *ptI=newConnI->getPointer();
5621   ptI[0]=0;
5622   const int *oldc=_nodal_connec->getConstPointer();
5623   const int *ci=_nodal_connec_index->getConstPointer();
5624   for(int i=0;i<nbOfCells;i++,ci++)
5625     {
5626       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5627         {
5628           for(int j=0;j<6;j++,pt+=5,ptI++)
5629             {
5630               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5631               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];
5632               *retPt++=i;
5633               ptI[1]=ptI[0]+5;
5634             }
5635         }
5636       else
5637         {
5638           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5639           ptI[1]=ptI[0]+ci[1]-ci[0];
5640           ptI++;
5641           *retPt++=i;
5642         }
5643     }
5644   _nodal_connec->decrRef();
5645   _nodal_connec=newConn.retn();
5646   _nodal_connec_index->decrRef();
5647   _nodal_connec_index=newConnI.retn();
5648   computeTypes();
5649   updateTime();
5650   return ret.retn();
5651 }
5652
5653 /*!
5654  * 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.
5655  * This method completly ignore coordinates.
5656  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5657  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5658  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5659  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5660  */
5661 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5662 {
5663   checkFullyDefined();
5664   if(getMeshDimension()!=2)
5665     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5666   int nbOfCells=getNumberOfCells();
5667   int *connI=_nodal_connec_index->getPointer();
5668   int newConnLgth=0;
5669   for(int i=0;i<nbOfCells;i++,connI++)
5670     {
5671       int offset=descIndex[i];
5672       int nbOfEdges=descIndex[i+1]-offset;
5673       //
5674       bool ddirect=desc[offset+nbOfEdges-1]>0;
5675       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5676       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5677       for(int j=0;j<nbOfEdges;j++)
5678         {
5679           bool direct=desc[offset+j]>0;
5680           int edgeId=std::abs(desc[offset+j])-1;
5681           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5682             {
5683               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5684               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5685               int ref2=direct?id1:id2;
5686               if(ref==ref2)
5687                 {
5688                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5689                   newConnLgth+=nbOfSubNodes-1;
5690                   ref=direct?id2:id1;
5691                 }
5692               else
5693                 {
5694                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5695                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5696                 }
5697             }
5698           else
5699             {
5700               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5701             }
5702         }
5703       newConnLgth++;//+1 is for cell type
5704       connI[1]=newConnLgth;
5705     }
5706   //
5707   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5708   newConn->alloc(newConnLgth,1);
5709   int *work=newConn->getPointer();
5710   for(int i=0;i<nbOfCells;i++)
5711     {
5712       *work++=INTERP_KERNEL::NORM_POLYGON;
5713       int offset=descIndex[i];
5714       int nbOfEdges=descIndex[i+1]-offset;
5715       for(int j=0;j<nbOfEdges;j++)
5716         {
5717           bool direct=desc[offset+j]>0;
5718           int edgeId=std::abs(desc[offset+j])-1;
5719           if(direct)
5720             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5721           else
5722             {
5723               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5724               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5725               work=std::copy(it,it+nbOfSubNodes-1,work);
5726             }
5727         }
5728     }
5729   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5730   _types.clear();
5731   if(nbOfCells>0)
5732     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5733 }
5734
5735 /*!
5736  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5737  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5738  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5739  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5740  * so it can be useful to call mergeNodes() before calling this method.
5741  *  \throw If \a this->getMeshDimension() <= 1.
5742  *  \throw If the coordinates array is not set.
5743  *  \throw If the nodal connectivity of cells is not defined.
5744  */
5745 void MEDCouplingUMesh::convertDegeneratedCells()
5746 {
5747   checkFullyDefined();
5748   if(getMeshDimension()<=1)
5749     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5750   int nbOfCells=getNumberOfCells();
5751   if(nbOfCells<1)
5752     return ;
5753   int initMeshLgth=getMeshLength();
5754   int *conn=_nodal_connec->getPointer();
5755   int *index=_nodal_connec_index->getPointer();
5756   int posOfCurCell=0;
5757   int newPos=0;
5758   int lgthOfCurCell;
5759   for(int i=0;i<nbOfCells;i++)
5760     {
5761       lgthOfCurCell=index[i+1]-posOfCurCell;
5762       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5763       int newLgth;
5764       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5765                                                                                                      conn+newPos+1,newLgth);
5766       conn[newPos]=newType;
5767       newPos+=newLgth+1;
5768       posOfCurCell=index[i+1];
5769       index[i+1]=newPos;
5770     }
5771   if(newPos!=initMeshLgth)
5772     _nodal_connec->reAlloc(newPos);
5773   computeTypes();
5774 }
5775
5776 /*!
5777  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5778  * A cell is considered to be oriented correctly if an angle between its
5779  * normal vector and a given vector is less than \c PI / \c 2.
5780  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5781  *         cells. 
5782  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5783  *         checked.
5784  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5785  *         is not cleared before filling in.
5786  *  \throw If \a this->getMeshDimension() != 2.
5787  *  \throw If \a this->getSpaceDimension() != 3.
5788  *
5789  *  \if ENABLE_EXAMPLES
5790  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5791  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5792  *  \endif
5793  */
5794 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5795 {
5796   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5797     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5798   int nbOfCells=getNumberOfCells();
5799   const int *conn=_nodal_connec->getConstPointer();
5800   const int *connI=_nodal_connec_index->getConstPointer();
5801   const double *coordsPtr=_coords->getConstPointer();
5802   for(int i=0;i<nbOfCells;i++)
5803     {
5804       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5805       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5806         {
5807           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5808           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5809             cells.push_back(i);
5810         }
5811     }
5812 }
5813
5814 /*!
5815  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5816  * considered to be oriented correctly if an angle between its normal vector and a
5817  * given vector is less than \c PI / \c 2. 
5818  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5819  *         cells. 
5820  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5821  *         checked.
5822  *  \throw If \a this->getMeshDimension() != 2.
5823  *  \throw If \a this->getSpaceDimension() != 3.
5824  *
5825  *  \if ENABLE_EXAMPLES
5826  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5827  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5828  *  \endif
5829  */
5830 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5831 {
5832   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5833     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5834   int nbOfCells=getNumberOfCells();
5835   int *conn=_nodal_connec->getPointer();
5836   const int *connI=_nodal_connec_index->getConstPointer();
5837   const double *coordsPtr=_coords->getConstPointer();
5838   bool isModified=false;
5839   for(int i=0;i<nbOfCells;i++)
5840     {
5841       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5842       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5843         {
5844           bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5845           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5846             {
5847               isModified=true;
5848               if(!isQuadratic)
5849                 {
5850                   std::vector<int> tmp(connI[i+1]-connI[i]-2);
5851                   std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5852                   std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5853                 }
5854               else
5855                 {
5856                   int sz(((int)(connI[i+1]-connI[i]-1))/2);
5857                   std::vector<int> tmp0(sz-1),tmp1(sz);
5858                   std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5859                   std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5860                   std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5861                   std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5862                 }
5863             }
5864         }
5865     }
5866   if(isModified)
5867     _nodal_connec->declareAsNew();
5868   updateTime();
5869 }
5870
5871 /*!
5872  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5873  * oriented facets. The normal vector of the facet should point out of the cell.
5874  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5875  *         is not cleared before filling in.
5876  *  \throw If \a this->getMeshDimension() != 3.
5877  *  \throw If \a this->getSpaceDimension() != 3.
5878  *  \throw If the coordinates array is not set.
5879  *  \throw If the nodal connectivity of cells is not defined.
5880  *
5881  *  \if ENABLE_EXAMPLES
5882  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5883  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5884  *  \endif
5885  */
5886 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5887 {
5888   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5889     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5890   int nbOfCells=getNumberOfCells();
5891   const int *conn=_nodal_connec->getConstPointer();
5892   const int *connI=_nodal_connec_index->getConstPointer();
5893   const double *coordsPtr=_coords->getConstPointer();
5894   for(int i=0;i<nbOfCells;i++)
5895     {
5896       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5897       if(type==INTERP_KERNEL::NORM_POLYHED)
5898         {
5899           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5900             cells.push_back(i);
5901         }
5902     }
5903 }
5904
5905 /*!
5906  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5907  * out of the cell. 
5908  *  \throw If \a this->getMeshDimension() != 3.
5909  *  \throw If \a this->getSpaceDimension() != 3.
5910  *  \throw If the coordinates array is not set.
5911  *  \throw If the nodal connectivity of cells is not defined.
5912  *  \throw If the reparation fails.
5913  *
5914  *  \if ENABLE_EXAMPLES
5915  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5916  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5917  *  \endif
5918  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5919  */
5920 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5921 {
5922   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5923     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5924   int nbOfCells=getNumberOfCells();
5925   int *conn=_nodal_connec->getPointer();
5926   const int *connI=_nodal_connec_index->getConstPointer();
5927   const double *coordsPtr=_coords->getConstPointer();
5928   for(int i=0;i<nbOfCells;i++)
5929     {
5930       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5931       if(type==INTERP_KERNEL::NORM_POLYHED)
5932         {
5933           try
5934           {
5935               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5936                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5937           }
5938           catch(INTERP_KERNEL::Exception& e)
5939           {
5940               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5941               throw INTERP_KERNEL::Exception(oss.str().c_str());
5942           }
5943         }
5944     }
5945   updateTime();
5946 }
5947
5948 /*!
5949  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5950  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5951  * according to which the first facet of the cell should be oriented to have the normal vector
5952  * pointing out of cell.
5953  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5954  *         cells. The caller is to delete this array using decrRef() as it is no more
5955  *         needed. 
5956  *  \throw If \a this->getMeshDimension() != 3.
5957  *  \throw If \a this->getSpaceDimension() != 3.
5958  *  \throw If the coordinates array is not set.
5959  *  \throw If the nodal connectivity of cells is not defined.
5960  *
5961  *  \if ENABLE_EXAMPLES
5962  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5963  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5964  *  \endif
5965  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5966  */
5967 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5968 {
5969   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5970   if(getMeshDimension()!=3)
5971     throw INTERP_KERNEL::Exception(msg);
5972   int spaceDim=getSpaceDimension();
5973   if(spaceDim!=3)
5974     throw INTERP_KERNEL::Exception(msg);
5975   //
5976   int nbOfCells=getNumberOfCells();
5977   int *conn=_nodal_connec->getPointer();
5978   const int *connI=_nodal_connec_index->getConstPointer();
5979   const double *coo=getCoords()->getConstPointer();
5980   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5981   for(int i=0;i<nbOfCells;i++)
5982     {
5983       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5984       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5985         {
5986           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5987             {
5988               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5989               cells->pushBackSilent(i);
5990             }
5991         }
5992     }
5993   return cells.retn();
5994 }
5995
5996 /*!
5997  * This method is a faster method to correct orientation of all 3D cells in \a this.
5998  * 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.
5999  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6000  * 
6001  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6002  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6003  */
6004 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6005 {
6006   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6007     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6008   int nbOfCells=getNumberOfCells();
6009   int *conn=_nodal_connec->getPointer();
6010   const int *connI=_nodal_connec_index->getConstPointer();
6011   const double *coordsPtr=_coords->getConstPointer();
6012   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6013   for(int i=0;i<nbOfCells;i++)
6014     {
6015       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6016       switch(type)
6017       {
6018         case INTERP_KERNEL::NORM_TETRA4:
6019           {
6020             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6021               {
6022                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6023                 ret->pushBackSilent(i);
6024               }
6025             break;
6026           }
6027         case INTERP_KERNEL::NORM_PYRA5:
6028           {
6029             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6030               {
6031                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6032                 ret->pushBackSilent(i);
6033               }
6034             break;
6035           }
6036         case INTERP_KERNEL::NORM_PENTA6:
6037         case INTERP_KERNEL::NORM_HEXA8:
6038         case INTERP_KERNEL::NORM_HEXGP12:
6039           {
6040             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6041               {
6042                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6043                 ret->pushBackSilent(i);
6044               }
6045             break;
6046           }
6047         case INTERP_KERNEL::NORM_POLYHED:
6048           {
6049             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6050               {
6051                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6052                 ret->pushBackSilent(i);
6053               }
6054             break;
6055           }
6056         default:
6057           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 !");
6058       }
6059     }
6060   updateTime();
6061   return ret.retn();
6062 }
6063
6064 /*!
6065  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6066  * If it is not the case an exception will be thrown.
6067  * This method is fast because the first cell of \a this is used to compute the plane.
6068  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6069  * \param pos output of size at least 3 used to store a point owned of searched plane.
6070  */
6071 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6072 {
6073   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6074     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6075   const int *conn=_nodal_connec->getConstPointer();
6076   const int *connI=_nodal_connec_index->getConstPointer();
6077   const double *coordsPtr=_coords->getConstPointer();
6078   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6079   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6080 }
6081
6082 /*!
6083  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6084  * cells. Currently cells of the following types are treated:
6085  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6086  * For a cell of other type an exception is thrown.
6087  * Space dimension of a 2D mesh can be either 2 or 3.
6088  * The Edge Ratio of a cell \f$t\f$ is: 
6089  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6090  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6091  *  the smallest edge lengths of \f$t\f$.
6092  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6093  *          cells and one time, lying on \a this mesh. The caller is to delete this
6094  *          field using decrRef() as it is no more needed. 
6095  *  \throw If the coordinates array is not set.
6096  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6097  *  \throw If the connectivity data array has more than one component.
6098  *  \throw If the connectivity data array has a named component.
6099  *  \throw If the connectivity index data array has more than one component.
6100  *  \throw If the connectivity index data array has a named component.
6101  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6102  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6103  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6104  */
6105 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6106 {
6107   checkCoherency();
6108   int spaceDim=getSpaceDimension();
6109   int meshDim=getMeshDimension();
6110   if(spaceDim!=2 && spaceDim!=3)
6111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6112   if(meshDim!=2 && meshDim!=3)
6113     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6114   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6115   ret->setMesh(this);
6116   int nbOfCells=getNumberOfCells();
6117   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6118   arr->alloc(nbOfCells,1);
6119   double *pt=arr->getPointer();
6120   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6121   const int *conn=_nodal_connec->getConstPointer();
6122   const int *connI=_nodal_connec_index->getConstPointer();
6123   const double *coo=_coords->getConstPointer();
6124   double tmp[12];
6125   for(int i=0;i<nbOfCells;i++,pt++)
6126     {
6127       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6128       switch(t)
6129       {
6130         case INTERP_KERNEL::NORM_TRI3:
6131           {
6132             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6133             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6134             break;
6135           }
6136         case INTERP_KERNEL::NORM_QUAD4:
6137           {
6138             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6139             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6140             break;
6141           }
6142         case INTERP_KERNEL::NORM_TETRA4:
6143           {
6144             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6145             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6146             break;
6147           }
6148         default:
6149           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6150       }
6151       conn+=connI[i+1]-connI[i];
6152     }
6153   ret->setName("EdgeRatio");
6154   ret->synchronizeTimeWithSupport();
6155   return ret.retn();
6156 }
6157
6158 /*!
6159  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6160  * cells. Currently cells of the following types are treated:
6161  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6162  * For a cell of other type an exception is thrown.
6163  * Space dimension of a 2D mesh can be either 2 or 3.
6164  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6165  *          cells and one time, lying on \a this mesh. The caller is to delete this
6166  *          field using decrRef() as it is no more needed. 
6167  *  \throw If the coordinates array is not set.
6168  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6169  *  \throw If the connectivity data array has more than one component.
6170  *  \throw If the connectivity data array has a named component.
6171  *  \throw If the connectivity index data array has more than one component.
6172  *  \throw If the connectivity index data array has a named component.
6173  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6174  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6175  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6176  */
6177 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6178 {
6179   checkCoherency();
6180   int spaceDim=getSpaceDimension();
6181   int meshDim=getMeshDimension();
6182   if(spaceDim!=2 && spaceDim!=3)
6183     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6184   if(meshDim!=2 && meshDim!=3)
6185     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6186   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6187   ret->setMesh(this);
6188   int nbOfCells=getNumberOfCells();
6189   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6190   arr->alloc(nbOfCells,1);
6191   double *pt=arr->getPointer();
6192   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6193   const int *conn=_nodal_connec->getConstPointer();
6194   const int *connI=_nodal_connec_index->getConstPointer();
6195   const double *coo=_coords->getConstPointer();
6196   double tmp[12];
6197   for(int i=0;i<nbOfCells;i++,pt++)
6198     {
6199       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6200       switch(t)
6201       {
6202         case INTERP_KERNEL::NORM_TRI3:
6203           {
6204             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6205             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6206             break;
6207           }
6208         case INTERP_KERNEL::NORM_QUAD4:
6209           {
6210             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6211             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6212             break;
6213           }
6214         case INTERP_KERNEL::NORM_TETRA4:
6215           {
6216             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6217             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6218             break;
6219           }
6220         default:
6221           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6222       }
6223       conn+=connI[i+1]-connI[i];
6224     }
6225   ret->setName("AspectRatio");
6226   ret->synchronizeTimeWithSupport();
6227   return ret.retn();
6228 }
6229
6230 /*!
6231  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6232  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6233  * treated: INTERP_KERNEL::NORM_QUAD4.
6234  * For a cell of other type an exception is thrown.
6235  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6236  *          cells and one time, lying on \a this mesh. The caller is to delete this
6237  *          field using decrRef() as it is no more needed. 
6238  *  \throw If the coordinates array is not set.
6239  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6240  *  \throw If the connectivity data array has more than one component.
6241  *  \throw If the connectivity data array has a named component.
6242  *  \throw If the connectivity index data array has more than one component.
6243  *  \throw If the connectivity index data array has a named component.
6244  *  \throw If \a this->getMeshDimension() != 2.
6245  *  \throw If \a this->getSpaceDimension() != 3.
6246  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6247  */
6248 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6249 {
6250   checkCoherency();
6251   int spaceDim=getSpaceDimension();
6252   int meshDim=getMeshDimension();
6253   if(spaceDim!=3)
6254     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6255   if(meshDim!=2)
6256     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6257   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6258   ret->setMesh(this);
6259   int nbOfCells=getNumberOfCells();
6260   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6261   arr->alloc(nbOfCells,1);
6262   double *pt=arr->getPointer();
6263   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6264   const int *conn=_nodal_connec->getConstPointer();
6265   const int *connI=_nodal_connec_index->getConstPointer();
6266   const double *coo=_coords->getConstPointer();
6267   double tmp[12];
6268   for(int i=0;i<nbOfCells;i++,pt++)
6269     {
6270       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6271       switch(t)
6272       {
6273         case INTERP_KERNEL::NORM_QUAD4:
6274           {
6275             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6276             *pt=INTERP_KERNEL::quadWarp(tmp);
6277             break;
6278           }
6279         default:
6280           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6281       }
6282       conn+=connI[i+1]-connI[i];
6283     }
6284   ret->setName("Warp");
6285   ret->synchronizeTimeWithSupport();
6286   return ret.retn();
6287 }
6288
6289
6290 /*!
6291  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6292  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6293  * treated: INTERP_KERNEL::NORM_QUAD4.
6294  * For a cell of other type an exception is thrown.
6295  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6296  *          cells and one time, lying on \a this mesh. The caller is to delete this
6297  *          field using decrRef() as it is no more needed. 
6298  *  \throw If the coordinates array is not set.
6299  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6300  *  \throw If the connectivity data array has more than one component.
6301  *  \throw If the connectivity data array has a named component.
6302  *  \throw If the connectivity index data array has more than one component.
6303  *  \throw If the connectivity index data array has a named component.
6304  *  \throw If \a this->getMeshDimension() != 2.
6305  *  \throw If \a this->getSpaceDimension() != 3.
6306  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6307  */
6308 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6309 {
6310   checkCoherency();
6311   int spaceDim=getSpaceDimension();
6312   int meshDim=getMeshDimension();
6313   if(spaceDim!=3)
6314     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6315   if(meshDim!=2)
6316     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6317   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6318   ret->setMesh(this);
6319   int nbOfCells=getNumberOfCells();
6320   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6321   arr->alloc(nbOfCells,1);
6322   double *pt=arr->getPointer();
6323   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6324   const int *conn=_nodal_connec->getConstPointer();
6325   const int *connI=_nodal_connec_index->getConstPointer();
6326   const double *coo=_coords->getConstPointer();
6327   double tmp[12];
6328   for(int i=0;i<nbOfCells;i++,pt++)
6329     {
6330       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6331       switch(t)
6332       {
6333         case INTERP_KERNEL::NORM_QUAD4:
6334           {
6335             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6336             *pt=INTERP_KERNEL::quadSkew(tmp);
6337             break;
6338           }
6339         default:
6340           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6341       }
6342       conn+=connI[i+1]-connI[i];
6343     }
6344   ret->setName("Skew");
6345   ret->synchronizeTimeWithSupport();
6346   return ret.retn();
6347 }
6348
6349 /*!
6350  * This method aggregate the bbox of each cell and put it into bbox parameter.
6351  * 
6352  * \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)
6353  *                         For all other cases this input parameter is ignored.
6354  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6355  * 
6356  * \throw If \a this is not fully set (coordinates and connectivity).
6357  * \throw If a cell in \a this has no valid nodeId.
6358  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6359  */
6360 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6361 {
6362   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6363   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.
6364     return getBoundingBoxForBBTreeFast();
6365   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6366     {
6367       bool presenceOfQuadratic(false);
6368       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6369         {
6370           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6371           if(cm.isQuadratic())
6372             presenceOfQuadratic=true;
6373         }
6374       if(!presenceOfQuadratic)
6375         return getBoundingBoxForBBTreeFast();
6376       if(mDim==2 && sDim==2)
6377         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6378       else
6379         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6380     }
6381   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) !");
6382 }
6383
6384 /*!
6385  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6386  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6387  * 
6388  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6389  * 
6390  * \throw If \a this is not fully set (coordinates and connectivity).
6391  * \throw If a cell in \a this has no valid nodeId.
6392  */
6393 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6394 {
6395   checkFullyDefined();
6396   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6397   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6398   double *bbox(ret->getPointer());
6399   for(int i=0;i<nbOfCells*spaceDim;i++)
6400     {
6401       bbox[2*i]=std::numeric_limits<double>::max();
6402       bbox[2*i+1]=-std::numeric_limits<double>::max();
6403     }
6404   const double *coordsPtr(_coords->getConstPointer());
6405   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6406   for(int i=0;i<nbOfCells;i++)
6407     {
6408       int offset=connI[i]+1;
6409       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6410       for(int j=0;j<nbOfNodesForCell;j++)
6411         {
6412           int nodeId=conn[offset+j];
6413           if(nodeId>=0 && nodeId<nbOfNodes)
6414             {
6415               for(int k=0;k<spaceDim;k++)
6416                 {
6417                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6418                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6419                 }
6420               kk++;
6421             }
6422         }
6423       if(kk==0)
6424         {
6425           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6426           throw INTERP_KERNEL::Exception(oss.str().c_str());
6427         }
6428     }
6429   return ret.retn();
6430 }
6431
6432 /*!
6433  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6434  * useful for 2D meshes having quadratic cells
6435  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6436  * the two extremities of the arc of circle).
6437  * 
6438  * \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)
6439  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6440  * \throw If \a this is not fully defined.
6441  * \throw If \a this is not a mesh with meshDimension equal to 2.
6442  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6443  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6444  */
6445 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6446 {
6447   checkFullyDefined();
6448   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6449   if(spaceDim!=2 || mDim!=2)
6450     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!");
6451   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6452   double *bbox(ret->getPointer());
6453   const double *coords(_coords->getConstPointer());
6454   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6455   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6456     {
6457       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6458       int sz(connI[1]-connI[0]-1);
6459       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6460       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6461       INTERP_KERNEL::QuadraticPolygon *pol(0);
6462       for(int j=0;j<sz;j++)
6463         {
6464           int nodeId(conn[*connI+1+j]);
6465           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6466         }
6467       if(!cm.isQuadratic())
6468         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6469       else
6470         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6471       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6472       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6473     }
6474   return ret.retn();
6475 }
6476
6477 /*!
6478  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6479  * useful for 2D meshes having quadratic cells
6480  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6481  * the two extremities of the arc of circle).
6482  * 
6483  * \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)
6484  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6485  * \throw If \a this is not fully defined.
6486  * \throw If \a this is not a mesh with meshDimension equal to 1.
6487  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6488  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6489  */
6490 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6491 {
6492   checkFullyDefined();
6493   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6494   if(spaceDim!=2 || mDim!=1)
6495     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!");
6496   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6497   double *bbox(ret->getPointer());
6498   const double *coords(_coords->getConstPointer());
6499   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6500   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6501     {
6502       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6503       int sz(connI[1]-connI[0]-1);
6504       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6505       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6506       INTERP_KERNEL::Edge *edge(0);
6507       for(int j=0;j<sz;j++)
6508         {
6509           int nodeId(conn[*connI+1+j]);
6510           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6511         }
6512       if(!cm.isQuadratic())
6513         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6514       else
6515         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6516       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6517       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6518     }
6519   return ret.retn();
6520 }
6521
6522 /// @cond INTERNAL
6523
6524 namespace ParaMEDMEMImpl
6525 {
6526   class ConnReader
6527   {
6528   public:
6529     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6530     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6531   private:
6532     const int *_conn;
6533     int _val;
6534   };
6535
6536   class ConnReader2
6537   {
6538   public:
6539     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6540     bool operator() (const int& pos) { return _conn[pos]==_val; }
6541   private:
6542     const int *_conn;
6543     int _val;
6544   };
6545 }
6546
6547 /// @endcond
6548
6549 /*!
6550  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6551  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6552  * \a this is composed in cell types.
6553  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6554  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6555  * This parameter is kept only for compatibility with other methode listed above.
6556  */
6557 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6558 {
6559   checkConnectivityFullyDefined();
6560   const int *conn=_nodal_connec->getConstPointer();
6561   const int *connI=_nodal_connec_index->getConstPointer();
6562   const int *work=connI;
6563   int nbOfCells=getNumberOfCells();
6564   std::size_t n=getAllGeoTypes().size();
6565   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6566   std::set<INTERP_KERNEL::NormalizedCellType> types;
6567   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6568     {
6569       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6570       if(types.find(typ)!=types.end())
6571         {
6572           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6573           oss << " is not contiguous !";
6574           throw INTERP_KERNEL::Exception(oss.str().c_str());
6575         }
6576       types.insert(typ);
6577       ret[3*i]=typ;
6578       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6579       ret[3*i+1]=(int)std::distance(work,work2);
6580       work=work2;
6581     }
6582   return ret;
6583 }
6584
6585 /*!
6586  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6587  * only for types cell, type node is not managed.
6588  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6589  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6590  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6591  * If 2 or more same geometric type is in \a code and exception is thrown too.
6592  *
6593  * This method firstly checks
6594  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6595  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6596  * an exception is thrown too.
6597  * 
6598  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6599  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6600  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6601  */
6602 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6603 {
6604   if(code.empty())
6605     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6606   std::size_t sz=code.size();
6607   std::size_t n=sz/3;
6608   if(sz%3!=0)
6609     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6610   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6611   int nb=0;
6612   bool isNoPflUsed=true;
6613   for(std::size_t i=0;i<n;i++)
6614     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6615       {
6616         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6617         nb+=code[3*i+1];
6618         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6619           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6620         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6621       }
6622   if(types.size()!=n)
6623     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6624   if(isNoPflUsed)
6625     {
6626       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6627         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6628       if(types.size()==_types.size())
6629         return 0;
6630     }
6631   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6632   ret->alloc(nb,1);
6633   int *retPtr=ret->getPointer();
6634   const int *connI=_nodal_connec_index->getConstPointer();
6635   const int *conn=_nodal_connec->getConstPointer();
6636   int nbOfCells=getNumberOfCells();
6637   const int *i=connI;
6638   int kk=0;
6639   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6640     {
6641       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6642       int offset=(int)std::distance(connI,i);
6643       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6644       int nbOfCellsOfCurType=(int)std::distance(i,j);
6645       if(code[3*kk+2]==-1)
6646         for(int k=0;k<nbOfCellsOfCurType;k++)
6647           *retPtr++=k+offset;
6648       else
6649         {
6650           int idInIdsPerType=code[3*kk+2];
6651           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6652             {
6653               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6654               if(zePfl)
6655                 {
6656                   zePfl->checkAllocated();
6657                   if(zePfl->getNumberOfComponents()==1)
6658                     {
6659                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6660                         {
6661                           if(*k>=0 && *k<nbOfCellsOfCurType)
6662                             *retPtr=(*k)+offset;
6663                           else
6664                             {
6665                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6666                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6667                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6668                             }
6669                         }
6670                     }
6671                   else
6672                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6673                 }
6674               else
6675                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6676             }
6677           else
6678             {
6679               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6680               oss << " should be in [0," << idsPerType.size() << ") !";
6681               throw INTERP_KERNEL::Exception(oss.str().c_str());
6682             }
6683         }
6684       i=j;
6685     }
6686   return ret.retn();
6687 }
6688
6689 /*!
6690  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6691  * 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.
6692  * 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.
6693  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6694  * 
6695  * \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.
6696  * \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,
6697  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6698  * \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.
6699  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6700  * \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
6701  */
6702 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6703 {
6704   if(!profile)
6705     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6706   if(profile->getNumberOfComponents()!=1)
6707     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6708   checkConnectivityFullyDefined();
6709   const int *conn=_nodal_connec->getConstPointer();
6710   const int *connI=_nodal_connec_index->getConstPointer();
6711   int nbOfCells=getNumberOfCells();
6712   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6713   std::vector<int> typeRangeVals(1);
6714   for(const int *i=connI;i!=connI+nbOfCells;)
6715     {
6716       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6717       if(std::find(types.begin(),types.end(),curType)!=types.end())
6718         {
6719           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6720         }
6721       types.push_back(curType);
6722       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6723       typeRangeVals.push_back((int)std::distance(connI,i));
6724     }
6725   //
6726   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6727   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6728   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6729   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6730   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6731   //
6732   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6733   code.resize(3*nbOfCastsFinal);
6734   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6735   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6736   for(int i=0;i<nbOfCastsFinal;i++)
6737     {
6738       int castId=castsPresent->getIJ(i,0);
6739       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6740       idsInPflPerType2.push_back(tmp3);
6741       code[3*i]=(int)types[castId];
6742       code[3*i+1]=tmp3->getNumberOfTuples();
6743       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6744       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6745         {
6746           tmp4->copyStringInfoFrom(*profile);
6747           idsPerType2.push_back(tmp4);
6748           code[3*i+2]=(int)idsPerType2.size()-1;
6749         }
6750       else
6751         {
6752           code[3*i+2]=-1;
6753         }
6754     }
6755   std::size_t sz2=idsInPflPerType2.size();
6756   idsInPflPerType.resize(sz2);
6757   for(std::size_t i=0;i<sz2;i++)
6758     {
6759       DataArrayInt *locDa=idsInPflPerType2[i];
6760       locDa->incrRef();
6761       idsInPflPerType[i]=locDa;
6762     }
6763   std::size_t sz=idsPerType2.size();
6764   idsPerType.resize(sz);
6765   for(std::size_t i=0;i<sz;i++)
6766     {
6767       DataArrayInt *locDa=idsPerType2[i];
6768       locDa->incrRef();
6769       idsPerType[i]=locDa;
6770     }
6771 }
6772
6773 /*!
6774  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6775  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6776  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6777  * 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.
6778  */
6779 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6780 {
6781   checkFullyDefined();
6782   nM1LevMesh->checkFullyDefined();
6783   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6784     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6785   if(_coords!=nM1LevMesh->getCoords())
6786     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6787   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6788   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6789   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6790   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6791   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6792   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6793   tmp->setConnectivity(tmp0,tmp1);
6794   tmp->renumberCells(ret0->getConstPointer(),false);
6795   revDesc=tmp->getNodalConnectivity();
6796   revDescIndx=tmp->getNodalConnectivityIndex();
6797   DataArrayInt *ret=0;
6798   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6799     {
6800       int tmp2;
6801       ret->getMaxValue(tmp2);
6802       ret->decrRef();
6803       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6804       throw INTERP_KERNEL::Exception(oss.str().c_str());
6805     }
6806   nM1LevMeshIds=ret;
6807   //
6808   revDesc->incrRef();
6809   revDescIndx->incrRef();
6810   ret1->incrRef();
6811   ret0->incrRef();
6812   meshnM1Old2New=ret0;
6813   return ret1;
6814 }
6815
6816 /*!
6817  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6818  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6819  * in "Old to New" mode.
6820  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6821  *          this array using decrRef() as it is no more needed.
6822  *  \throw If the nodal connectivity of cells is not defined.
6823  */
6824 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6825 {
6826   checkConnectivityFullyDefined();
6827   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6828   renumberCells(ret->getConstPointer(),false);
6829   return ret.retn();
6830 }
6831
6832 /*!
6833  * This methods checks that cells are sorted by their types.
6834  * This method makes asumption (no check) that connectivity is correctly set before calling.
6835  */
6836 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6837 {
6838   checkFullyDefined();
6839   const int *conn=_nodal_connec->getConstPointer();
6840   const int *connI=_nodal_connec_index->getConstPointer();
6841   int nbOfCells=getNumberOfCells();
6842   std::set<INTERP_KERNEL::NormalizedCellType> types;
6843   for(const int *i=connI;i!=connI+nbOfCells;)
6844     {
6845       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6846       if(types.find(curType)!=types.end())
6847         return false;
6848       types.insert(curType);
6849       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6850     }
6851   return true;
6852 }
6853
6854 /*!
6855  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6856  * The geometric type order is specified by MED file.
6857  * 
6858  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6859  */
6860 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6861 {
6862   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6863 }
6864
6865 /*!
6866  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6867  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6868  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6869  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6870  */
6871 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6872 {
6873   checkFullyDefined();
6874   const int *conn=_nodal_connec->getConstPointer();
6875   const int *connI=_nodal_connec_index->getConstPointer();
6876   int nbOfCells=getNumberOfCells();
6877   if(nbOfCells==0)
6878     return true;
6879   int lastPos=-1;
6880   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6881   for(const int *i=connI;i!=connI+nbOfCells;)
6882     {
6883       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6884       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6885       if(isTypeExists!=orderEnd)
6886         {
6887           int pos=(int)std::distance(orderBg,isTypeExists);
6888           if(pos<=lastPos)
6889             return false;
6890           lastPos=pos;
6891           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6892         }
6893       else
6894         {
6895           if(sg.find(curType)==sg.end())
6896             {
6897               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6898               sg.insert(curType);
6899             }
6900           else
6901             return false;
6902         }
6903     }
6904   return true;
6905 }
6906
6907 /*!
6908  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6909  * 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
6910  * 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'.
6911  */
6912 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6913 {
6914   checkConnectivityFullyDefined();
6915   int nbOfCells=getNumberOfCells();
6916   const int *conn=_nodal_connec->getConstPointer();
6917   const int *connI=_nodal_connec_index->getConstPointer();
6918   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6919   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6920   tmpa->alloc(nbOfCells,1);
6921   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6922   tmpb->fillWithZero();
6923   int *tmp=tmpa->getPointer();
6924   int *tmp2=tmpb->getPointer();
6925   for(const int *i=connI;i!=connI+nbOfCells;i++)
6926     {
6927       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6928       if(where!=orderEnd)
6929         {
6930           int pos=(int)std::distance(orderBg,where);
6931           tmp2[pos]++;
6932           tmp[std::distance(connI,i)]=pos;
6933         }
6934       else
6935         {
6936           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6937           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6938           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6939           throw INTERP_KERNEL::Exception(oss.str().c_str());
6940         }
6941     }
6942   nbPerType=tmpb.retn();
6943   return tmpa.retn();
6944 }
6945
6946 /*!
6947  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6948  *
6949  * \return a new object containing the old to new correspondance.
6950  *
6951  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6952  */
6953 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6954 {
6955   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6956 }
6957
6958 /*!
6959  * 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.
6960  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6961  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6962  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6963  */
6964 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6965 {
6966   DataArrayInt *nbPerType=0;
6967   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6968   nbPerType->decrRef();
6969   return tmpa->buildPermArrPerLevel();
6970 }
6971
6972 /*!
6973  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6974  * The number of cells remains unchanged after the call of this method.
6975  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6976  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6977  *
6978  * \return the array giving the correspondance old to new.
6979  */
6980 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6981 {
6982   checkFullyDefined();
6983   computeTypes();
6984   const int *conn=_nodal_connec->getConstPointer();
6985   const int *connI=_nodal_connec_index->getConstPointer();
6986   int nbOfCells=getNumberOfCells();
6987   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6988   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6989     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6990       {
6991         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6992         types.push_back(curType);
6993         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6994       }
6995   DataArrayInt *ret=DataArrayInt::New();
6996   ret->alloc(nbOfCells,1);
6997   int *retPtr=ret->getPointer();
6998   std::fill(retPtr,retPtr+nbOfCells,-1);
6999   int newCellId=0;
7000   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7001     {
7002       for(const int *i=connI;i!=connI+nbOfCells;i++)
7003         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7004           retPtr[std::distance(connI,i)]=newCellId++;
7005     }
7006   renumberCells(retPtr,false);
7007   return ret;
7008 }
7009
7010 /*!
7011  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7012  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7013  * This method makes asumption that connectivity is correctly set before calling.
7014  */
7015 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7016 {
7017   checkConnectivityFullyDefined();
7018   const int *conn=_nodal_connec->getConstPointer();
7019   const int *connI=_nodal_connec_index->getConstPointer();
7020   int nbOfCells=getNumberOfCells();
7021   std::vector<MEDCouplingUMesh *> ret;
7022   for(const int *i=connI;i!=connI+nbOfCells;)
7023     {
7024       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7025       int beginCellId=(int)std::distance(connI,i);
7026       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7027       int endCellId=(int)std::distance(connI,i);
7028       int sz=endCellId-beginCellId;
7029       int *cells=new int[sz];
7030       for(int j=0;j<sz;j++)
7031         cells[j]=beginCellId+j;
7032       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7033       delete [] cells;
7034       ret.push_back(m);
7035     }
7036   return ret;
7037 }
7038
7039 /*!
7040  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7041  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7042  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7043  *
7044  * \return a newly allocated instance, that the caller must manage.
7045  * \throw If \a this contains more than one geometric type.
7046  * \throw If the nodal connectivity of \a this is not fully defined.
7047  * \throw If the internal data is not coherent.
7048  */
7049 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7050 {
7051   checkConnectivityFullyDefined();
7052   if(_types.size()!=1)
7053     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7054   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7055   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7056   ret->setCoords(getCoords());
7057   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7058   if(retC)
7059     {
7060       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7061       retC->setNodalConnectivity(c);
7062     }
7063   else
7064     {
7065       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7066       if(!retD)
7067         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7068       DataArrayInt *c=0,*ci=0;
7069       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7070       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7071       retD->setNodalConnectivity(cs,cis);
7072     }
7073   return ret.retn();
7074 }
7075
7076 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7077 {
7078   checkConnectivityFullyDefined();
7079   if(_types.size()!=1)
7080     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7081   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7082   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7083   if(cm.isDynamic())
7084     {
7085       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7086       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7087       throw INTERP_KERNEL::Exception(oss.str().c_str());
7088     }
7089   int nbCells=getNumberOfCells();
7090   int typi=(int)typ;
7091   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7092   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7093   int *outPtr=connOut->getPointer();
7094   const int *conn=_nodal_connec->begin();
7095   const int *connI=_nodal_connec_index->begin();
7096   nbNodesPerCell++;
7097   for(int i=0;i<nbCells;i++,connI++)
7098     {
7099       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7100         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7101       else
7102         {
7103           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 << ") !";
7104           throw INTERP_KERNEL::Exception(oss.str().c_str());
7105         }
7106     }
7107   return connOut.retn();
7108 }
7109
7110 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7111 {
7112   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7113   checkConnectivityFullyDefined();
7114   if(_types.size()!=1)
7115     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7116   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7117   if(lgth<nbCells)
7118     throw INTERP_KERNEL::Exception(msg0);
7119   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7120   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7121   int *cp(c->getPointer()),*cip(ci->getPointer());
7122   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7123   cip[0]=0;
7124   for(int i=0;i<nbCells;i++,cip++,incip++)
7125     {
7126       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7127       int delta(stop-strt);
7128       if(delta>=1)
7129         {
7130           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7131             cp=std::copy(incp+strt,incp+stop,cp);
7132           else
7133             throw INTERP_KERNEL::Exception(msg0);
7134         }
7135       else
7136         throw INTERP_KERNEL::Exception(msg0);
7137       cip[1]=cip[0]+delta;
7138     }
7139   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7140 }
7141
7142 /*!
7143  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7144  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7145  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7146  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7147  * are not used here to avoid the build of big permutation array.
7148  *
7149  * \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
7150  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7151  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7152  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7153  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7154  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7155  * \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
7156  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7157  */
7158 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7159                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7160                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7161 {
7162   std::vector<const MEDCouplingUMesh *> ms2;
7163   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7164     if(*it)
7165       {
7166         (*it)->checkConnectivityFullyDefined();
7167         ms2.push_back(*it);
7168       }
7169   if(ms2.empty())
7170     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7171   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7172   int meshDim=ms2[0]->getMeshDimension();
7173   std::vector<const MEDCouplingUMesh *> m1ssm;
7174   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7175   //
7176   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7177   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7178   int fake=0,rk=0;
7179   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7180   ret1->alloc(0,1); ret2->alloc(0,1);
7181   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7182     {
7183       if(meshDim!=(*it)->getMeshDimension())
7184         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7185       if(refCoo!=(*it)->getCoords())
7186         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7187       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7188       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7189       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7190       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7191         {
7192           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7193           m1ssmSingleAuto.push_back(singleCell);
7194           m1ssmSingle.push_back(singleCell);
7195           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7196         }
7197     }
7198   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7199   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7200   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7201   for(std::size_t i=0;i<m1ssm.size();i++)
7202     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7203   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7204   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7205   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7206   return ret0.retn();
7207 }
7208
7209 /*!
7210  * This method returns a newly created DataArrayInt instance.
7211  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7212  */
7213 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7214 {
7215   checkFullyDefined();
7216   const int *conn=_nodal_connec->getConstPointer();
7217   const int *connIndex=_nodal_connec_index->getConstPointer();
7218   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7219   for(const int *w=begin;w!=end;w++)
7220     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7221       ret->pushBackSilent(*w);
7222   return ret.retn();
7223 }
7224
7225 /*!
7226  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7227  * are in [0:getNumberOfCells())
7228  */
7229 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7230 {
7231   checkFullyDefined();
7232   const int *conn=_nodal_connec->getConstPointer();
7233   const int *connI=_nodal_connec_index->getConstPointer();
7234   int nbOfCells=getNumberOfCells();
7235   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7236   int *tmp=new int[nbOfCells];
7237   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7238     {
7239       int j=0;
7240       for(const int *i=connI;i!=connI+nbOfCells;i++)
7241         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7242           tmp[std::distance(connI,i)]=j++;
7243     }
7244   DataArrayInt *ret=DataArrayInt::New();
7245   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7246   ret->copyStringInfoFrom(*da);
7247   int *retPtr=ret->getPointer();
7248   const int *daPtr=da->getConstPointer();
7249   int nbOfElems=da->getNbOfElems();
7250   for(int k=0;k<nbOfElems;k++)
7251     retPtr[k]=tmp[daPtr[k]];
7252   delete [] tmp;
7253   return ret;
7254 }
7255
7256 /*!
7257  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7258  * This method \b works \b for mesh sorted by type.
7259  * cells whose ids is in 'idsPerGeoType' array.
7260  * This method conserves coords and name of mesh.
7261  */
7262 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7263 {
7264   std::vector<int> code=getDistributionOfTypes();
7265   std::size_t nOfTypesInThis=code.size()/3;
7266   int sz=0,szOfType=0;
7267   for(std::size_t i=0;i<nOfTypesInThis;i++)
7268     {
7269       if(code[3*i]!=type)
7270         sz+=code[3*i+1];
7271       else
7272         szOfType=code[3*i+1];
7273     }
7274   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7275     if(*work<0 || *work>=szOfType)
7276       {
7277         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7278         oss << ". It should be in [0," << szOfType << ") !";
7279         throw INTERP_KERNEL::Exception(oss.str().c_str());
7280       }
7281   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7282   int *idsPtr=idsTokeep->getPointer();
7283   int offset=0;
7284   for(std::size_t i=0;i<nOfTypesInThis;i++)
7285     {
7286       if(code[3*i]!=type)
7287         for(int j=0;j<code[3*i+1];j++)
7288           *idsPtr++=offset+j;
7289       else
7290         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7291       offset+=code[3*i+1];
7292     }
7293   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7294   ret->copyTinyInfoFrom(this);
7295   return ret.retn();
7296 }
7297
7298 /*!
7299  * This method returns a vector of size 'this->getNumberOfCells()'.
7300  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7301  */
7302 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7303 {
7304   int ncell=getNumberOfCells();
7305   std::vector<bool> ret(ncell);
7306   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7307   const int *c=getNodalConnectivity()->getConstPointer();
7308   for(int i=0;i<ncell;i++)
7309     {
7310       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7311       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7312       ret[i]=cm.isQuadratic();
7313     }
7314   return ret;
7315 }
7316
7317 /*!
7318  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7319  */
7320 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7321 {
7322   if(other->getType()!=UNSTRUCTURED)
7323     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7324   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7325   return MergeUMeshes(this,otherC);
7326 }
7327
7328 /*!
7329  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7330  * computed by averaging coordinates of cell nodes, so this method is not a right
7331  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7332  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7333  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7334  *          components. The caller is to delete this array using decrRef() as it is
7335  *          no more needed.
7336  *  \throw If the coordinates array is not set.
7337  *  \throw If the nodal connectivity of cells is not defined.
7338  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7339  */
7340 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7341 {
7342   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7343   int spaceDim=getSpaceDimension();
7344   int nbOfCells=getNumberOfCells();
7345   ret->alloc(nbOfCells,spaceDim);
7346   ret->copyStringInfoFrom(*getCoords());
7347   double *ptToFill=ret->getPointer();
7348   const int *nodal=_nodal_connec->getConstPointer();
7349   const int *nodalI=_nodal_connec_index->getConstPointer();
7350   const double *coor=_coords->getConstPointer();
7351   for(int i=0;i<nbOfCells;i++)
7352     {
7353       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7354       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7355       ptToFill+=spaceDim;
7356     }
7357   return ret.retn();
7358 }
7359
7360 /*!
7361  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7362  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7363  * 
7364  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7365  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7366  * 
7367  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7368  * \throw If \a this is not fully defined (coordinates and connectivity)
7369  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7370  */
7371 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7372 {
7373   checkFullyDefined();
7374   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7375   int spaceDim=getSpaceDimension();
7376   int nbOfCells=getNumberOfCells();
7377   int nbOfNodes=getNumberOfNodes();
7378   ret->alloc(nbOfCells,spaceDim);
7379   double *ptToFill=ret->getPointer();
7380   const int *nodal=_nodal_connec->getConstPointer();
7381   const int *nodalI=_nodal_connec_index->getConstPointer();
7382   const double *coor=_coords->getConstPointer();
7383   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7384     {
7385       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7386       std::fill(ptToFill,ptToFill+spaceDim,0.);
7387       if(type!=INTERP_KERNEL::NORM_POLYHED)
7388         {
7389           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7390             {
7391               if(*conn>=0 && *conn<nbOfNodes)
7392                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7393               else
7394                 {
7395                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7396                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7397                 }
7398             }
7399           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7400           if(nbOfNodesInCell>0)
7401             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7402           else
7403             {
7404               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7405               throw INTERP_KERNEL::Exception(oss.str().c_str());
7406             }
7407         }
7408       else
7409         {
7410           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7411           s.erase(-1);
7412           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7413             {
7414               if(*it>=0 && *it<nbOfNodes)
7415                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7416               else
7417                 {
7418                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7419                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7420                 }
7421             }
7422           if(!s.empty())
7423             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7424           else
7425             {
7426               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7427               throw INTERP_KERNEL::Exception(oss.str().c_str());
7428             }
7429         }
7430     }
7431   return ret.retn();
7432 }
7433
7434 /*!
7435  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7436  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7437  * are specified via an array of cell ids. 
7438  *  \warning Validity of the specified cell ids is not checked! 
7439  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7440  *  \param [in] begin - an array of cell ids of interest.
7441  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7442  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7443  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7444  *          caller is to delete this array using decrRef() as it is no more needed. 
7445  *  \throw If the coordinates array is not set.
7446  *  \throw If the nodal connectivity of cells is not defined.
7447  *
7448  *  \if ENABLE_EXAMPLES
7449  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7450  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7451  *  \endif
7452  */
7453 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7454 {
7455   DataArrayDouble *ret=DataArrayDouble::New();
7456   int spaceDim=getSpaceDimension();
7457   int nbOfTuple=(int)std::distance(begin,end);
7458   ret->alloc(nbOfTuple,spaceDim);
7459   double *ptToFill=ret->getPointer();
7460   double *tmp=new double[spaceDim];
7461   const int *nodal=_nodal_connec->getConstPointer();
7462   const int *nodalI=_nodal_connec_index->getConstPointer();
7463   const double *coor=_coords->getConstPointer();
7464   for(const int *w=begin;w!=end;w++)
7465     {
7466       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7467       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7468       ptToFill+=spaceDim;
7469     }
7470   delete [] tmp;
7471   return ret;
7472 }
7473
7474 /*!
7475  * 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".
7476  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7477  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7478  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7479  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7480  * 
7481  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7482  * \throw If spaceDim!=3 or meshDim!=2.
7483  * \throw If connectivity of \a this is invalid.
7484  * \throw If connectivity of a cell in \a this points to an invalid node.
7485  */
7486 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7487 {
7488   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7489   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7490   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7491     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7492   ret->alloc(nbOfCells,4);
7493   double *retPtr(ret->getPointer());
7494   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7495   const double *coor(_coords->begin());
7496   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7497     {
7498       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7499       if(nodalI[1]-nodalI[0]>=3)
7500         {
7501           for(int j=0;j<3;j++)
7502             {
7503               int nodeId(nodal[nodalI[0]+1+j]);
7504               if(nodeId>=0 && nodeId<nbOfNodes)
7505                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7506               else
7507                 {
7508                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7509                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7510                 }
7511             }
7512         }
7513       else
7514         {
7515           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7516           throw INTERP_KERNEL::Exception(oss.str().c_str());
7517         }
7518       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7519       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7520     }
7521   return ret.retn();
7522 }
7523
7524 /*!
7525  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7526  * 
7527  */
7528 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7529 {
7530   if(!da)
7531     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7532   da->checkAllocated();
7533   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7534   ret->setCoords(da);
7535   int nbOfTuples=da->getNumberOfTuples();
7536   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7537   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7538   c->alloc(2*nbOfTuples,1);
7539   cI->alloc(nbOfTuples+1,1);
7540   int *cp=c->getPointer();
7541   int *cip=cI->getPointer();
7542   *cip++=0;
7543   for(int i=0;i<nbOfTuples;i++)
7544     {
7545       *cp++=INTERP_KERNEL::NORM_POINT1;
7546       *cp++=i;
7547       *cip++=2*(i+1);
7548     }
7549   ret->setConnectivity(c,cI,true);
7550   return ret.retn();
7551 }
7552 /*!
7553  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7554  * Cells and nodes of
7555  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7556  *  \param [in] mesh1 - the first mesh.
7557  *  \param [in] mesh2 - the second mesh.
7558  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7559  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7560  *          is no more needed.
7561  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7562  *  \throw If the coordinates array is not set in none of the meshes.
7563  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7564  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7565  */
7566 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7567 {
7568   std::vector<const MEDCouplingUMesh *> tmp(2);
7569   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7570   return MergeUMeshes(tmp);
7571 }
7572
7573 /*!
7574  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7575  * Cells and nodes of
7576  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7577  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7578  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7579  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7580  *          is no more needed.
7581  *  \throw If \a a.size() == 0.
7582  *  \throw If \a a[ *i* ] == NULL.
7583  *  \throw If the coordinates array is not set in none of the meshes.
7584  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7585  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7586  */
7587 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7588 {
7589   std::size_t sz=a.size();
7590   if(sz==0)
7591     return MergeUMeshesLL(a);
7592   for(std::size_t ii=0;ii<sz;ii++)
7593     if(!a[ii])
7594       {
7595         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7596         throw INTERP_KERNEL::Exception(oss.str().c_str());
7597       }
7598   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7599   std::vector< const MEDCouplingUMesh * > aa(sz);
7600   int spaceDim=-3;
7601   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7602     {
7603       const MEDCouplingUMesh *cur=a[i];
7604       const DataArrayDouble *coo=cur->getCoords();
7605       if(coo)
7606         spaceDim=coo->getNumberOfComponents();
7607     }
7608   if(spaceDim==-3)
7609     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7610   for(std::size_t i=0;i<sz;i++)
7611     {
7612       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7613       aa[i]=bb[i];
7614     }
7615   return MergeUMeshesLL(aa);
7616 }
7617
7618 /// @cond INTERNAL
7619
7620 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7621 {
7622   if(a.empty())
7623     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7624   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7625   int meshDim=(*it)->getMeshDimension();
7626   int nbOfCells=(*it)->getNumberOfCells();
7627   int meshLgth=(*it++)->getMeshLength();
7628   for(;it!=a.end();it++)
7629     {
7630       if(meshDim!=(*it)->getMeshDimension())
7631         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7632       nbOfCells+=(*it)->getNumberOfCells();
7633       meshLgth+=(*it)->getMeshLength();
7634     }
7635   std::vector<const MEDCouplingPointSet *> aps(a.size());
7636   std::copy(a.begin(),a.end(),aps.begin());
7637   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7638   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7639   ret->setCoords(pts);
7640   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7641   c->alloc(meshLgth,1);
7642   int *cPtr=c->getPointer();
7643   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7644   cI->alloc(nbOfCells+1,1);
7645   int *cIPtr=cI->getPointer();
7646   *cIPtr++=0;
7647   int offset=0;
7648   int offset2=0;
7649   for(it=a.begin();it!=a.end();it++)
7650     {
7651       int curNbOfCell=(*it)->getNumberOfCells();
7652       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7653       const int *curC=(*it)->_nodal_connec->getConstPointer();
7654       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7655       for(int j=0;j<curNbOfCell;j++)
7656         {
7657           const int *src=curC+curCI[j];
7658           *cPtr++=*src++;
7659           for(;src!=curC+curCI[j+1];src++,cPtr++)
7660             {
7661               if(*src!=-1)
7662                 *cPtr=*src+offset2;
7663               else
7664                 *cPtr=-1;
7665             }
7666         }
7667       offset+=curCI[curNbOfCell];
7668       offset2+=(*it)->getNumberOfNodes();
7669     }
7670   //
7671   ret->setConnectivity(c,cI,true);
7672   return ret.retn();
7673 }
7674
7675 /// @endcond
7676
7677 /*!
7678  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7679  * dimension and sharing the node coordinates array.
7680  * All cells of the first mesh precede all cells of the second mesh
7681  * within the result mesh. 
7682  *  \param [in] mesh1 - the first mesh.
7683  *  \param [in] mesh2 - the second mesh.
7684  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7685  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7686  *          is no more needed.
7687  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7688  *  \throw If the meshes do not share the node coordinates array.
7689  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7690  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7691  */
7692 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7693 {
7694   std::vector<const MEDCouplingUMesh *> tmp(2);
7695   tmp[0]=mesh1; tmp[1]=mesh2;
7696   return MergeUMeshesOnSameCoords(tmp);
7697 }
7698
7699 /*!
7700  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7701  * dimension and sharing the node coordinates array.
7702  * All cells of the *i*-th mesh precede all cells of the
7703  * (*i*+1)-th mesh within the result mesh.
7704  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7705  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7706  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7707  *          is no more needed.
7708  *  \throw If \a a.size() == 0.
7709  *  \throw If \a a[ *i* ] == NULL.
7710  *  \throw If the meshes do not share the node coordinates array.
7711  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7712  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7713  */
7714 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7715 {
7716   if(meshes.empty())
7717     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7718   for(std::size_t ii=0;ii<meshes.size();ii++)
7719     if(!meshes[ii])
7720       {
7721         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7722         throw INTERP_KERNEL::Exception(oss.str().c_str());
7723       }
7724   const DataArrayDouble *coords=meshes.front()->getCoords();
7725   int meshDim=meshes.front()->getMeshDimension();
7726   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7727   int meshLgth=0;
7728   int meshIndexLgth=0;
7729   for(;iter!=meshes.end();iter++)
7730     {
7731       if(coords!=(*iter)->getCoords())
7732         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7733       if(meshDim!=(*iter)->getMeshDimension())
7734         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7735       meshLgth+=(*iter)->getMeshLength();
7736       meshIndexLgth+=(*iter)->getNumberOfCells();
7737     }
7738   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7739   nodal->alloc(meshLgth,1);
7740   int *nodalPtr=nodal->getPointer();
7741   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7742   nodalIndex->alloc(meshIndexLgth+1,1);
7743   int *nodalIndexPtr=nodalIndex->getPointer();
7744   int offset=0;
7745   for(iter=meshes.begin();iter!=meshes.end();iter++)
7746     {
7747       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7748       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7749       int nbOfCells=(*iter)->getNumberOfCells();
7750       int meshLgth2=(*iter)->getMeshLength();
7751       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7752       if(iter!=meshes.begin())
7753         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7754       else
7755         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7756       offset+=meshLgth2;
7757     }
7758   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7759   ret->setName("merge");
7760   ret->setMeshDimension(meshDim);
7761   ret->setConnectivity(nodal,nodalIndex,true);
7762   ret->setCoords(coords);
7763   return ret;
7764 }
7765
7766 /*!
7767  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7768  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7769  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7770  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7771  * New" mode are returned for each input mesh.
7772  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7773  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7774  *          valid values [0,1,2], see zipConnectivityTraducer().
7775  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7776  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7777  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7778  *          no more needed.
7779  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7780  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7781  *          is no more needed.
7782  *  \throw If \a meshes.size() == 0.
7783  *  \throw If \a meshes[ *i* ] == NULL.
7784  *  \throw If the meshes do not share the node coordinates array.
7785  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7786  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7787  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7788  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7789  */
7790 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7791 {
7792   //All checks are delegated to MergeUMeshesOnSameCoords
7793   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7794   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7795   corr.resize(meshes.size());
7796   std::size_t nbOfMeshes=meshes.size();
7797   int offset=0;
7798   const int *o2nPtr=o2n->getConstPointer();
7799   for(std::size_t i=0;i<nbOfMeshes;i++)
7800     {
7801       DataArrayInt *tmp=DataArrayInt::New();
7802       int curNbOfCells=meshes[i]->getNumberOfCells();
7803       tmp->alloc(curNbOfCells,1);
7804       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7805       offset+=curNbOfCells;
7806       tmp->setName(meshes[i]->getName());
7807       corr[i]=tmp;
7808     }
7809   return ret.retn();
7810 }
7811
7812 /*!
7813  * Makes all given meshes share the nodal connectivity array. The common connectivity
7814  * array is created by concatenating the connectivity arrays of all given meshes. All
7815  * the given meshes must be of the same space dimension but dimension of cells **can
7816  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7817  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7818  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7819  *  \param [in,out] meshes - a vector of meshes to update.
7820  *  \throw If any of \a meshes is NULL.
7821  *  \throw If the coordinates array is not set in any of \a meshes.
7822  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7823  *  \throw If \a meshes are of different space dimension.
7824  */
7825 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7826 {
7827   std::size_t sz=meshes.size();
7828   if(sz==0 || sz==1)
7829     return;
7830   std::vector< const DataArrayDouble * > coords(meshes.size());
7831   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7832   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7833     {
7834       if((*it))
7835         {
7836           (*it)->checkConnectivityFullyDefined();
7837           const DataArrayDouble *coo=(*it)->getCoords();
7838           if(coo)
7839             *it2=coo;
7840           else
7841             {
7842               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7843               oss << " has no coordinate array defined !";
7844               throw INTERP_KERNEL::Exception(oss.str().c_str());
7845             }
7846         }
7847       else
7848         {
7849           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7850           oss << " is null !";
7851           throw INTERP_KERNEL::Exception(oss.str().c_str());
7852         }
7853     }
7854   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7855   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7856   int offset=(*it)->getNumberOfNodes();
7857   (*it++)->setCoords(res);
7858   for(;it!=meshes.end();it++)
7859     {
7860       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7861       (*it)->setCoords(res);
7862       (*it)->shiftNodeNumbersInConn(offset);
7863       offset+=oldNumberOfNodes;
7864     }
7865 }
7866
7867 /*!
7868  * Merges nodes coincident with a given precision within all given meshes that share
7869  * the nodal connectivity array. The given meshes **can be of different** mesh
7870  * dimension. 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  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7875  *  \throw If any of \a meshes is NULL.
7876  *  \throw If the \a meshes do not share the same node coordinates array.
7877  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7878  */
7879 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7880 {
7881   if(meshes.empty())
7882     return ;
7883   std::set<const DataArrayDouble *> s;
7884   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7885     {
7886       if(*it)
7887         s.insert((*it)->getCoords());
7888       else
7889         {
7890           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 !";
7891           throw INTERP_KERNEL::Exception(oss.str().c_str());
7892         }
7893     }
7894   if(s.size()!=1)
7895     {
7896       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 !";
7897       throw INTERP_KERNEL::Exception(oss.str().c_str());
7898     }
7899   const DataArrayDouble *coo=*(s.begin());
7900   if(!coo)
7901     return;
7902   //
7903   DataArrayInt *comm,*commI;
7904   coo->findCommonTuples(eps,-1,comm,commI);
7905   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7906   int oldNbOfNodes=coo->getNumberOfTuples();
7907   int newNbOfNodes;
7908   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7909   if(oldNbOfNodes==newNbOfNodes)
7910     return ;
7911   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7912   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7913     {
7914       (*it)->renumberNodesInConn(o2n->getConstPointer());
7915       (*it)->setCoords(newCoords);
7916     } 
7917 }
7918
7919 /*!
7920  * 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.
7921  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7922  * \param isQuad specifies the policy of connectivity.
7923  * @ret in/out parameter in which the result will be append
7924  */
7925 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7926 {
7927   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7928   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7929   ret.push_back(cm.getExtrudedType());
7930   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7931   switch(flatType)
7932   {
7933     case INTERP_KERNEL::NORM_POINT1:
7934       {
7935         ret.push_back(connBg[1]);
7936         ret.push_back(connBg[1]+nbOfNodesPerLev);
7937         break;
7938       }
7939     case INTERP_KERNEL::NORM_SEG2:
7940       {
7941         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7942         ret.insert(ret.end(),conn,conn+4);
7943         break;
7944       }
7945     case INTERP_KERNEL::NORM_SEG3:
7946       {
7947         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7948         ret.insert(ret.end(),conn,conn+8);
7949         break;
7950       }
7951     case INTERP_KERNEL::NORM_QUAD4:
7952       {
7953         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7954         ret.insert(ret.end(),conn,conn+8);
7955         break;
7956       }
7957     case INTERP_KERNEL::NORM_TRI3:
7958       {
7959         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7960         ret.insert(ret.end(),conn,conn+6);
7961         break;
7962       }
7963     case INTERP_KERNEL::NORM_TRI6:
7964       {
7965         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,
7966           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7967         ret.insert(ret.end(),conn,conn+15);
7968         break;
7969       }
7970     case INTERP_KERNEL::NORM_QUAD8:
7971       {
7972         int conn[20]={
7973           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7974           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7975           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7976         };
7977         ret.insert(ret.end(),conn,conn+20);
7978         break;
7979       }
7980     case INTERP_KERNEL::NORM_POLYGON:
7981       {
7982         std::back_insert_iterator< std::vector<int> > ii(ret);
7983         std::copy(connBg+1,connEnd,ii);
7984         *ii++=-1;
7985         std::reverse_iterator<const int *> rConnBg(connEnd);
7986         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7987         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7988         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7989         for(std::size_t i=0;i<nbOfRadFaces;i++)
7990           {
7991             *ii++=-1;
7992             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7993             std::copy(conn,conn+4,ii);
7994           }
7995         break;
7996       }
7997     default:
7998       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7999   }
8000 }
8001
8002 /*!
8003  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8004  */
8005 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8006 {
8007   std::size_t i, ip1;
8008   double v[3]={0.,0.,0.};
8009   std::size_t sz=std::distance(begin,end);
8010   if(isQuadratic)
8011     sz/=2;
8012   for(i=0;i<sz;i++)
8013     {
8014       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];
8015       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8016       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8017     }
8018   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8019
8020   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8021   // SEG3 forming a circle):
8022   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8023     {
8024       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8025       for(std::size_t j=0;j<sz;j++)
8026         {
8027           if (j%2)  // current point i is quadratic, next point i+1 is standard
8028             {
8029               i = sz+j;
8030               ip1 = (j+1)%sz; // ip1 = "i+1"
8031             }
8032           else      // current point i is standard, next point i+1 is quadratic
8033             {
8034               i = j;
8035               ip1 = j+sz;
8036             }
8037           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8038           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8039           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8040         }
8041       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8042     }
8043   return (ret>0.);
8044 }
8045
8046 /*!
8047  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8048  */
8049 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8050 {
8051   std::vector<std::pair<int,int> > edges;
8052   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8053   const int *bgFace=begin;
8054   for(std::size_t i=0;i<nbOfFaces;i++)
8055     {
8056       const int *endFace=std::find(bgFace+1,end,-1);
8057       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8058       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8059         {
8060           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8061           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8062             return false;
8063           edges.push_back(p1);
8064         }
8065       bgFace=endFace+1;
8066     }
8067   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8068 }
8069
8070 /*!
8071  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8072  */
8073 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8074 {
8075   double vec0[3],vec1[3];
8076   std::size_t sz=std::distance(begin,end);
8077   if(sz%2!=0)
8078     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8079   int nbOfNodes=(int)sz/2;
8080   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8081   const double *pt0=coords+3*begin[0];
8082   const double *pt1=coords+3*begin[nbOfNodes];
8083   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8084   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8085 }
8086
8087 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8088 {
8089   std::size_t sz=std::distance(begin,end);
8090   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8091   std::size_t nbOfNodes(sz/2);
8092   std::copy(begin,end,(int *)tmp);
8093   for(std::size_t j=1;j<nbOfNodes;j++)
8094     {
8095       begin[j]=tmp[nbOfNodes-j];
8096       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8097     }
8098 }
8099
8100 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8101 {
8102   std::size_t sz=std::distance(begin,end);
8103   if(sz!=4)
8104     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8105   double vec0[3],vec1[3];
8106   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8107   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]; 
8108   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;
8109 }
8110
8111 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8112 {
8113   std::size_t sz=std::distance(begin,end);
8114   if(sz!=5)
8115     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8116   double vec0[3];
8117   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8118   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8119   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8120 }
8121
8122 /*!
8123  * 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 ) 
8124  * 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
8125  * a 2D space.
8126  *
8127  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8128  * \param [in] coords the coordinates with nb of components exactly equal to 3
8129  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8130  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8131  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8132  */
8133 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8134 {
8135   int nbFaces=std::count(begin+1,end,-1)+1;
8136   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8137   double *vPtr=v->getPointer();
8138   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8139   double *pPtr=p->getPointer();
8140   const int *stFaceConn=begin+1;
8141   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8142     {
8143       const int *endFaceConn=std::find(stFaceConn,end,-1);
8144       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8145       stFaceConn=endFaceConn+1;
8146     }
8147   pPtr=p->getPointer(); vPtr=v->getPointer();
8148   DataArrayInt *comm1=0,*commI1=0;
8149   v->findCommonTuples(eps,-1,comm1,commI1);
8150   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8151   const int *comm1Ptr=comm1->getConstPointer();
8152   const int *commI1Ptr=commI1->getConstPointer();
8153   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8154   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8155   //
8156   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8157   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8158   mm->finishInsertingCells();
8159   //
8160   for(int i=0;i<nbOfGrps1;i++)
8161     {
8162       int vecId=comm1Ptr[commI1Ptr[i]];
8163       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8164       DataArrayInt *comm2=0,*commI2=0;
8165       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8166       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8167       const int *comm2Ptr=comm2->getConstPointer();
8168       const int *commI2Ptr=commI2->getConstPointer();
8169       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8170       for(int j=0;j<nbOfGrps2;j++)
8171         {
8172           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8173             {
8174               res->insertAtTheEnd(begin,end);
8175               res->pushBackSilent(-1);
8176             }
8177           else
8178             {
8179               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8180               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8181               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8182               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8183               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8184               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8185               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8186               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8187               const int *idsNodePtr=idsNode->getConstPointer();
8188               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];
8189               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8190               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8191               if(std::abs(norm)>eps)
8192                 {
8193                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8194                   mm3->rotate(center,vec,angle);
8195                 }
8196               mm3->changeSpaceDimension(2);
8197               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8198               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8199               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8200               int nbOfCells=mm4->getNumberOfCells();
8201               for(int k=0;k<nbOfCells;k++)
8202                 {
8203                   int l=0;
8204                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8205                     res->pushBackSilent(idsNodePtr[*work]);
8206                   res->pushBackSilent(-1);
8207                 }
8208             }
8209         }
8210     }
8211   res->popBackSilent();
8212 }
8213
8214 /*!
8215  * 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
8216  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8217  * 
8218  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8219  * \param [in] coords coordinates expected to have 3 components.
8220  * \param [in] begin start of the nodal connectivity of the face.
8221  * \param [in] end end of the nodal connectivity (excluded) of the face.
8222  * \param [out] v the normalized vector of size 3
8223  * \param [out] p the pos of plane
8224  */
8225 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8226 {
8227   std::size_t nbPoints=std::distance(begin,end);
8228   if(nbPoints<3)
8229     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8230   double vec[3]={0.,0.,0.};
8231   std::size_t j=0;
8232   bool refFound=false;
8233   for(;j<nbPoints-1 && !refFound;j++)
8234     {
8235       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8236       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8237       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8238       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8239       if(norm>eps)
8240         {
8241           refFound=true;
8242           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8243         }
8244     }
8245   for(std::size_t i=j;i<nbPoints-1;i++)
8246     {
8247       double curVec[3];
8248       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8249       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8250       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8251       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8252       if(norm<eps)
8253         continue;
8254       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8255       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];
8256       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8257       if(norm>eps)
8258         {
8259           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8260           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8261           return ;
8262         }
8263     }
8264   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8265 }
8266
8267 /*!
8268  * This method tries to obtain a well oriented polyhedron.
8269  * If the algorithm fails, an exception will be thrown.
8270  */
8271 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8272 {
8273   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8274   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8275   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8276   isPerm[0]=true;
8277   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8278   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8279   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8280   //
8281   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8282     {
8283       bgFace=begin;
8284       std::size_t smthChanged=0;
8285       for(std::size_t i=0;i<nbOfFaces;i++)
8286         {
8287           endFace=std::find(bgFace+1,end,-1);
8288           nbOfEdgesInFace=std::distance(bgFace,endFace);
8289           if(!isPerm[i])
8290             {
8291               bool b;
8292               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8293                 {
8294                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8295                   std::pair<int,int> p2(p1.second,p1.first);
8296                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8297                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8298                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8299                 }
8300               if(isPerm[i])
8301                 { 
8302                   if(!b)
8303                     std::reverse(bgFace+1,endFace);
8304                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8305                     {
8306                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8307                       std::pair<int,int> p2(p1.second,p1.first);
8308                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8309                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8310                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8311                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8312                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8313                       if(it!=edgesOK.end())
8314                         {
8315                           edgesOK.erase(it);
8316                           edgesFinished.push_back(p1);
8317                         }
8318                       else
8319                         edgesOK.push_back(p1);
8320                     }
8321                 }
8322             }
8323           bgFace=endFace+1;
8324         }
8325       if(smthChanged==0)
8326         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8327     }
8328   if(!edgesOK.empty())
8329     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8330   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8331     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8332       bgFace=begin;
8333       for(std::size_t i=0;i<nbOfFaces;i++)
8334         {
8335           endFace=std::find(bgFace+1,end,-1);
8336           std::reverse(bgFace+1,endFace);
8337           bgFace=endFace+1;
8338         }
8339     }
8340 }
8341
8342 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8343 {
8344   int nbOfNodesExpected(skin->getNumberOfNodes());
8345   const int *n2oPtr(n2o->getConstPointer());
8346   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8347   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8348   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8349   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8350   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8351   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8352   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8353   if(nbOfNodesExpected<1)
8354     return ret.retn();
8355   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8356   *work++=n2oPtr[prevNode];
8357   for(int i=1;i<nbOfNodesExpected;i++)
8358     {
8359       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8360         {
8361           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8362           conn.erase(prevNode);
8363           if(conn.size()==1)
8364             {
8365               int curNode(*(conn.begin()));
8366               *work++=n2oPtr[curNode];
8367               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8368               shar.erase(prevCell);
8369               if(shar.size()==1)
8370                 {
8371                   prevCell=*(shar.begin());
8372                   prevNode=curNode;
8373                 }
8374               else
8375                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8376             }
8377           else
8378             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8379         }
8380       else
8381         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8382     }
8383   return ret.retn();
8384 }
8385
8386 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8387 {
8388   int nbOfNodesExpected(skin->getNumberOfNodes());
8389   int nbOfTurn(nbOfNodesExpected/2);
8390   const int *n2oPtr(n2o->getConstPointer());
8391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8392   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8393   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8394   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8395   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8397   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8398   if(nbOfNodesExpected<1)
8399     return ret.retn();
8400   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8401   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8402   for(int i=1;i<nbOfTurn;i++)
8403     {
8404       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8405         {
8406           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8407           conn.erase(prevNode);
8408           if(conn.size()==1)
8409             {
8410               int curNode(*(conn.begin()));
8411               *work=n2oPtr[curNode];
8412               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8413               shar.erase(prevCell);
8414               if(shar.size()==1)
8415                 {
8416                   int curCell(*(shar.begin()));
8417                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8418                   prevCell=curCell;
8419                   prevNode=curNode;
8420                   work++;
8421                 }
8422               else
8423                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8424             }
8425           else
8426             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8427         }
8428       else
8429         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8430     }
8431   return ret.retn();
8432 }
8433
8434 /*!
8435  * This method makes the assumption spacedimension == meshdimension == 2.
8436  * This method works only for linear cells.
8437  * 
8438  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8439  */
8440 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8441 {
8442   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8443     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8444   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8445   int oldNbOfNodes(skin->getNumberOfNodes());
8446   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8447   int nbOfNodesExpected(skin->getNumberOfNodes());
8448   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8449   int nbCells(skin->getNumberOfCells());
8450   if(nbCells==nbOfNodesExpected)
8451     return buildUnionOf2DMeshLinear(skin,n2o);
8452   else if(2*nbCells==nbOfNodesExpected)
8453     return buildUnionOf2DMeshQuadratic(skin,n2o);
8454   else
8455     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8456 }
8457
8458 /*!
8459  * This method makes the assumption spacedimension == meshdimension == 3.
8460  * This method works only for linear cells.
8461  * 
8462  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8463  */
8464 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8465 {
8466   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8467     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8468   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8469   const int *conn=m->getNodalConnectivity()->getConstPointer();
8470   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8471   int nbOfCells=m->getNumberOfCells();
8472   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8473   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8474   if(nbOfCells<1)
8475     return ret.retn();
8476   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8477   for(int i=1;i<nbOfCells;i++)
8478     {
8479       *work++=-1;
8480       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8481     }
8482   return ret.retn();
8483 }
8484
8485 /*!
8486  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8487  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8488  */
8489 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8490 {
8491   double *w=zipFrmt;
8492   if(spaceDim==3)
8493     for(int i=0;i<nbOfNodesInCell;i++)
8494       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8495   else if(spaceDim==2)
8496     {
8497       for(int i=0;i<nbOfNodesInCell;i++)
8498         {
8499           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8500           *w++=0.;
8501         }
8502     }
8503   else
8504     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8505 }
8506
8507 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8508 {
8509   int nbOfCells=getNumberOfCells();
8510   if(nbOfCells<=0)
8511     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8512   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};
8513   ofs << "  <" << getVTKDataSetType() << ">\n";
8514   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8515   ofs << "      <PointData>\n" << pointData << std::endl;
8516   ofs << "      </PointData>\n";
8517   ofs << "      <CellData>\n" << cellData << std::endl;
8518   ofs << "      </CellData>\n";
8519   ofs << "      <Points>\n";
8520   if(getSpaceDimension()==3)
8521     _coords->writeVTK(ofs,8,"Points",byteData);
8522   else
8523     {
8524       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8525       coo->writeVTK(ofs,8,"Points",byteData);
8526     }
8527   ofs << "      </Points>\n";
8528   ofs << "      <Cells>\n";
8529   const int *cPtr=_nodal_connec->getConstPointer();
8530   const int *cIPtr=_nodal_connec_index->getConstPointer();
8531   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8532   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8533   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8534   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8535   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8536   int szFaceOffsets=0,szConn=0;
8537   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8538     {
8539       *w2=cPtr[cIPtr[i]];
8540       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8541         {
8542           *w1=-1;
8543           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8544           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8545         }
8546       else
8547         {
8548           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8549           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8550           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8551           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8552           w4=std::copy(c.begin(),c.end(),w4);
8553         }
8554     }
8555   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8556   types->writeVTK(ofs,8,"UInt8","types",byteData);
8557   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8558   if(szFaceOffsets!=0)
8559     {//presence of Polyhedra
8560       connectivity->reAlloc(szConn);
8561       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8562       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8563       w1=faces->getPointer();
8564       for(int i=0;i<nbOfCells;i++)
8565         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8566           {
8567             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8568             *w1++=nbFaces;
8569             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8570             for(int j=0;j<nbFaces;j++)
8571               {
8572                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8573                 *w1++=(int)std::distance(w6,w5);
8574                 w1=std::copy(w6,w5,w1);
8575                 w6=w5+1;
8576               }
8577           }
8578       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8579     }
8580   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8581   ofs << "      </Cells>\n";
8582   ofs << "    </Piece>\n";
8583   ofs << "  </" << getVTKDataSetType() << ">\n";
8584 }
8585
8586 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8587 {
8588   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8589   if(_mesh_dim==-2)
8590     { stream << " Not set !"; return ; }
8591   stream << " Mesh dimension : " << _mesh_dim << ".";
8592   if(_mesh_dim==-1)
8593     return ;
8594   if(!_coords)
8595     { stream << " No coordinates set !"; return ; }
8596   if(!_coords->isAllocated())
8597     { stream << " Coordinates set but not allocated !"; return ; }
8598   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8599   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8600   if(!_nodal_connec_index)
8601     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8602   if(!_nodal_connec_index->isAllocated())
8603     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8604   int lgth=_nodal_connec_index->getNumberOfTuples();
8605   int cpt=_nodal_connec_index->getNumberOfComponents();
8606   if(cpt!=1 || lgth<1)
8607     return ;
8608   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8609 }
8610
8611 std::string MEDCouplingUMesh::getVTKDataSetType() const
8612 {
8613   return std::string("UnstructuredGrid");
8614 }
8615
8616 /*!
8617  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8618  * returns a result mesh constituted by polygons.
8619  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8620  * all nodes from m2.
8621  * The meshes should be in 2D space. In
8622  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8623  * meshes.
8624  *  \param [in] m1 - the first input mesh which is a partitioned object.
8625  *  \param [in] m2 - the second input mesh which is a partition tool.
8626  *  \param [in] eps - precision used to detect coincident mesh entities.
8627  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8628  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8629  *         this array using decrRef() as it is no more needed.
8630  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8631  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8632  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8633  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8634  *         it is no more needed.  
8635  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8636  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8637  *         is no more needed.  
8638  *  \throw If the coordinates array is not set in any of the meshes.
8639  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8640  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8641  */
8642 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8643                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8644 {
8645   m1->checkFullyDefined();
8646   m2->checkFullyDefined();
8647   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8648     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8649
8650   // Step 1: compute all edge intersections (new nodes)
8651   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8652   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8653   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8654   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8655   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8656   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8657   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8658                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8659                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8660   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8661   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8662   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8663
8664   // Step 2: re-order newly created nodes according to the ordering found in m2
8665   std::vector< std::vector<int> > intersectEdge2;
8666   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8667   subDiv2.clear(); dd5=0; dd6=0;
8668
8669   // Step 3:
8670   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8671   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8672   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8673                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8674
8675   // Step 4: Prepare final result:
8676   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8677   addCooDa->alloc((int)(addCoo.size())/2,2);
8678   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8679   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8680   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8681   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8682   std::vector<const DataArrayDouble *> coordss(4);
8683   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8684   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8685   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8686   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8687   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8688   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8689   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8690   ret->setConnectivity(conn,connI,true);
8691   ret->setCoords(coo);
8692   cellNb1=c1.retn(); cellNb2=c2.retn();
8693   return ret.retn();
8694 }
8695
8696
8697 /**
8698  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
8699  * (newly created) nodes corresponding to the edge intersections.
8700  * Output params:
8701  * @param[out] cr, crI connectivity of the resulting mesh
8702  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
8703  * TODO: describe input parameters
8704  */
8705 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8706                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8707                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8708                                                          const std::vector<double>& addCoords,
8709                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8710 {
8711   static const int SPACEDIM=2;
8712   const double *coo1=m1->getCoords()->getConstPointer();
8713   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8714   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8715   int offset1=m1->getNumberOfNodes();
8716   const double *coo2=m2->getCoords()->getConstPointer();
8717   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8718   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8719   int offset2=offset1+m2->getNumberOfNodes();
8720   int offset3=offset2+((int)addCoords.size())/2;
8721   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8722   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8723   // Here a BBTree on 2D-cells, not on segments:
8724   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8725   int ncell1=m1->getNumberOfCells();
8726   crI.push_back(0);
8727   for(int i=0;i<ncell1;i++)
8728     {
8729       std::vector<int> candidates2;
8730       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8731       std::map<INTERP_KERNEL::Node *,int> mapp;
8732       std::map<int,INTERP_KERNEL::Node *> mappRev;
8733       INTERP_KERNEL::QuadraticPolygon pol1;
8734       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8735       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8736       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
8737       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8738       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
8739       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8740           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8741       //
8742       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
8743       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8744       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8745       for(it1.first();!it1.finished();it1.next())
8746         edges1.insert(it1.current()->getPtr());
8747       //
8748       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
8749       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8750       int ii=0;
8751       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8752         {
8753           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8754           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8755           // Complete mapping with elements coming from the current cell it2 in mesh2:
8756           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8757           // pol2 is the new QP in the final merged result.
8758           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8759               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
8760         }
8761       ii=0;
8762       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8763         {
8764           pol1.initLocationsWithOther(pol2s[ii]);
8765           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8766           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8767           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8768         }
8769       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
8770       // by m2 but that we still want to keep in the final result.
8771       if(!edges1.empty())
8772         {
8773           try
8774           {
8775               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8776           }
8777           catch(INTERP_KERNEL::Exception& e)
8778           {
8779               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();
8780               throw INTERP_KERNEL::Exception(oss.str().c_str());
8781           }
8782         }
8783       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8784         (*it).second->decrRef();
8785     }
8786 }
8787
8788 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8789 {
8790   std::map<INTERP_KERNEL::Node *,int>::const_iterator it(m.find(n));
8791   if(it==m.end())
8792     throw INTERP_KERNEL::Exception("Internal error in remapping !");
8793   int v((*it).second);
8794   if(v==forbVal0 || v==forbVal1)
8795     return ;
8796   if(std::find(isect.begin(),isect.end(),v)==isect.end())
8797     isect.push_back(v);
8798 }
8799
8800 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8801 {
8802   int sz(c.size());
8803   if(sz<=1)
8804     return false;
8805   bool presenceOfOn(false);
8806   for(int i=0;i<sz;i++)
8807     {
8808       INTERP_KERNEL::ElementaryEdge *e(c[i]);
8809       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
8810         continue ;
8811       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
8812       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
8813     }
8814   return presenceOfOn;
8815 }
8816
8817 /**
8818  * 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.
8819  * 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.
8820  * 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.
8821  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
8822  *
8823  * \return int - the number of new nodes created (in most of cases 0).
8824  * 
8825  * \throw If \a this is not coherent.
8826  * \throw If \a this has not spaceDim equal to 2.
8827  * \throw If \a this has not meshDim equal to 2.
8828  * \throw If some subcells needed to be split are orphan.
8829  * \sa MEDCouplingUMesh::conformize2D
8830  */
8831 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
8832 {
8833   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
8834     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
8835   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
8836   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
8837     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
8838   if(midOpt==0 && midOptI==0)
8839     {
8840       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
8841       return 0;
8842     }
8843   else if(midOpt!=0 && midOptI!=0)
8844     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
8845   else
8846     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
8847 }
8848
8849 /*!
8850  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
8851  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
8852  * 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
8853  * 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).
8854  * 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.
8855  * 
8856  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
8857  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
8858  *
8859  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
8860  * This method expects that all nodes in \a this are not closer than \a eps.
8861  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
8862  * 
8863  * \param [in] eps the relative error to detect merged edges.
8864  * \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
8865  *                           that the user is expected to deal with.
8866  *
8867  * \throw If \a this is not coherent.
8868  * \throw If \a this has not spaceDim equal to 2.
8869  * \throw If \a this has not meshDim equal to 2.
8870  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
8871  */
8872 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
8873 {
8874   static const int SPACEDIM=2;
8875   checkCoherency();
8876   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
8877     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
8878   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
8879   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
8880   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
8881   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
8882   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
8883   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
8884   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
8885   std::vector<double> addCoo;
8886   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
8887   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8888   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8889   for(int i=0;i<nDescCell;i++)
8890     {
8891       std::vector<int> candidates;
8892       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
8893       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8894         if(*it>i)
8895           {
8896             std::map<INTERP_KERNEL::Node *,int> m;
8897             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
8898                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
8899             INTERP_KERNEL::MergePoints merge;
8900             INTERP_KERNEL::QuadraticPolygon c1,c2;
8901             e1->intersectWith(e2,merge,c1,c2);
8902             e1->decrRef(); e2->decrRef();
8903             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
8904               overlapEdge[i].push_back(*it);
8905             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
8906               overlapEdge[*it].push_back(i);
8907             for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
8908               (*it2).first->decrRef();
8909           }
8910     }
8911   // splitting done. sort intersect point in intersectEdge.
8912   std::vector< std::vector<int> > middle(nDescCell);
8913   int nbOf2DCellsToBeSplit(0);
8914   bool middleNeedsToBeUsed(false);
8915   std::vector<bool> cells2DToTreat(nDescCell,false);
8916   for(int i=0;i<nDescCell;i++)
8917     {
8918       std::vector<int>& isect(intersectEdge[i]);
8919       int sz((int)isect.size());
8920       if(sz>1)
8921         {
8922           std::map<INTERP_KERNEL::Node *,int> m;
8923           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
8924           e->sortSubNodesAbs(coords,isect);
8925           e->decrRef();
8926           for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
8927             (*it2).first->decrRef();
8928         }
8929       if(sz!=0)
8930         {
8931           int idx0(rdi[i]),idx1(rdi[i+1]);
8932           if(idx1-idx0!=1)
8933             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
8934           if(!cells2DToTreat[rd[idx0]])
8935             {
8936               cells2DToTreat[rd[idx0]]=true;
8937               nbOf2DCellsToBeSplit++;
8938             }
8939           // try to reuse at most eventual 'middle' of SEG3
8940           std::vector<int>& mid(middle[i]);
8941           mid.resize(sz+1,-1);
8942           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
8943             {
8944               middleNeedsToBeUsed=true;
8945               const std::vector<int>& candidates(overlapEdge[i]);
8946               std::vector<int> trueCandidates;
8947               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
8948                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
8949                   trueCandidates.push_back(*itc);
8950               int stNode(c[ci[i]+1]),endNode(isect[0]);
8951               for(int j=0;j<sz+1;j++)
8952                 {
8953                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
8954                     {
8955                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
8956                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
8957                         { mid[j]=*itc; break; }
8958                     }
8959                   stNode=endNode;
8960                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
8961                 }
8962             }
8963         }
8964     }
8965   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
8966   if(nbOf2DCellsToBeSplit==0)
8967     return ret.retn();
8968   //
8969   int *retPtr(ret->getPointer());
8970   for(int i=0;i<nCell;i++)
8971     if(cells2DToTreat[i])
8972       *retPtr++=i;
8973   //
8974   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
8975   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
8976   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
8977   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
8978   if(middleNeedsToBeUsed)
8979     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
8980   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
8981   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
8982   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.
8983   setPartOfMySelf(ret->begin(),ret->end(),*modif);
8984   {
8985     bool areNodesMerged; int newNbOfNodes;
8986     if(nbOfNodesCreated!=0)
8987       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
8988   }
8989   return ret.retn();
8990 }
8991
8992 /*!
8993  * 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.
8994  * 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).
8995  * 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
8996  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
8997  * 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
8998  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
8999  *
9000  * 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
9001  * using new instance, idem for coordinates.
9002  *
9003  * 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.
9004  * 
9005  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
9006  *
9007  * \throw If \a this is not coherent.
9008  * \throw If \a this has not spaceDim equal to 2.
9009  * \throw If \a this has not meshDim equal to 2.
9010  * 
9011  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
9012  */
9013 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
9014 {
9015   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
9016   checkCoherency();
9017   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9018     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9019   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9020   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9021   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
9022   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
9023   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
9024   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
9025   const double *coords(_coords->begin());
9026   int *newciptr(newci->getPointer());
9027   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
9028     {
9029       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
9030         ret->pushBackSilent(i);
9031       newciptr[1]=newc->getNumberOfTuples();
9032     }
9033   //
9034   if(ret->empty())
9035     return ret.retn();
9036   if(!appendedCoords->empty())
9037     {
9038       appendedCoords->rearrange(2);
9039       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
9040       //non const part
9041       setCoords(newCoords);
9042     }
9043   //non const part
9044   setConnectivity(newc,newci,true);
9045   return ret.retn();
9046 }
9047
9048 /*!
9049  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
9050  * It builds the descending connectivity of the two meshes, and then using a binary tree
9051  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
9052  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
9053  */
9054 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
9055                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
9056                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
9057                                                    std::vector<double>& addCoo,
9058                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
9059 {
9060   static const int SPACEDIM=2;
9061   // Build desc connectivity
9062   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
9063   desc2=DataArrayInt::New();
9064   descIndx2=DataArrayInt::New();
9065   revDesc2=DataArrayInt::New();
9066   revDescIndx2=DataArrayInt::New();
9067   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9068   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
9069   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
9070   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
9071   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
9072   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
9073   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
9074
9075   // Build BB tree of all edges in the tool mesh (second mesh)
9076   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
9077   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9078   int nDescCell1=m1Desc->getNumberOfCells();
9079   int nDescCell2=m2Desc->getNumberOfCells();
9080   intersectEdge1.resize(nDescCell1);
9081   colinear2.resize(nDescCell2);
9082   subDiv2.resize(nDescCell2);
9083   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
9084
9085   std::vector<int> candidates1(1);
9086   int offset1=m1->getNumberOfNodes();
9087   int offset2=offset1+m2->getNumberOfNodes();
9088   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
9089     {
9090       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
9091       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9092       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
9093         {
9094           std::map<INTERP_KERNEL::Node *,int> map1,map2;
9095           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
9096           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
9097           candidates1[0]=i;
9098           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
9099           // 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
9100           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
9101           std::set<INTERP_KERNEL::Node *> nodes;
9102           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
9103           std::size_t szz(nodes.size());
9104           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
9105           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
9106           for(std::size_t iii=0;iii<szz;iii++,itt++)
9107             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
9108           // end of protection
9109           // Performs egde cutting:
9110           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
9111           delete pol2;
9112           delete pol1;
9113         }
9114       else
9115         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
9116     }
9117   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
9118   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
9119 }
9120
9121 /*!
9122  * This method performs the 2nd step of Partition of 2D mesh.
9123  * This method has 4 inputs :
9124  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
9125  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
9126  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
9127  * 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'
9128  * Nodes end up lying consecutively on a cutted edge.
9129  * \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.
9130  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
9131  * \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.
9132  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
9133  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
9134  */
9135 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9136                                            const std::vector<double>& addCoo,
9137                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
9138 {
9139   int offset1=m1->getNumberOfNodes();
9140   int ncell=m2->getNumberOfCells();
9141   const int *c=m2->getNodalConnectivity()->getConstPointer();
9142   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
9143   const double *coo=m2->getCoords()->getConstPointer();
9144   const double *cooBis=m1->getCoords()->getConstPointer();
9145   int offset2=offset1+m2->getNumberOfNodes();
9146   intersectEdge.resize(ncell);
9147   for(int i=0;i<ncell;i++,cI++)
9148     {
9149       const std::vector<int>& divs=subDiv[i];
9150       int nnode=cI[1]-cI[0]-1;
9151       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
9152       std::map<INTERP_KERNEL::Node *, int> mapp22;
9153       for(int j=0;j<nnode;j++)
9154         {
9155           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
9156           int nnid=c[(*cI)+j+1];
9157           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
9158           mapp22[nn]=nnid+offset1;
9159         }
9160       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
9161       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
9162         ((*it).second.first)->decrRef();
9163       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
9164       std::map<INTERP_KERNEL::Node *,int> mapp3;
9165       for(std::size_t j=0;j<divs.size();j++)
9166         {
9167           int id=divs[j];
9168           INTERP_KERNEL::Node *tmp=0;
9169           if(id<offset1)
9170             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
9171           else if(id<offset2)
9172             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
9173           else
9174             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
9175           addNodes[j]=tmp;
9176           mapp3[tmp]=id;
9177         }
9178       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
9179       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
9180         (*it)->decrRef();
9181       e->decrRef();
9182     }
9183 }
9184
9185 /*!
9186  * 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).
9187  * 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
9188  * with a plane. The result will be put in 'cut3DSuf' out parameter.
9189  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
9190  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
9191  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
9192  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
9193  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
9194  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
9195  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
9196  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
9197  * \param [out] cut3DSuf input/output param.
9198  */
9199 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
9200                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
9201                                                    const int *desc, const int *descIndx, 
9202                                                    std::vector< std::pair<int,int> >& cut3DSurf)
9203 {
9204   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
9205   int nbOf3DSurfCell=(int)cut3DSurf.size();
9206   for(int i=0;i<nbOf3DSurfCell;i++)
9207     {
9208       std::vector<int> res;
9209       int offset=descIndx[i];
9210       int nbOfSeg=descIndx[i+1]-offset;
9211       for(int j=0;j<nbOfSeg;j++)
9212         {
9213           int edgeId=desc[offset+j];
9214           int status=cut3DCurve[edgeId];
9215           if(status!=-2)
9216             {
9217               if(status>-1)
9218                 res.push_back(status);
9219               else
9220                 {
9221                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
9222                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
9223                 }
9224             }
9225         }
9226       switch(res.size())
9227       {
9228         case 2:
9229           {
9230             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9231             break;
9232           }
9233         case 1:
9234         case 0:
9235           {
9236             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
9237             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
9238             if(res.size()==2)
9239               {
9240                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9241               }
9242             else
9243               {
9244                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
9245               }
9246             break;
9247           }
9248         default:
9249           {// case when plane is on a multi colinear edge of a polyhedron
9250             if((int)res.size()==2*nbOfSeg)
9251               {
9252                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
9253               }
9254             else
9255               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
9256           }
9257       }
9258     }
9259 }
9260
9261 /*!
9262  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
9263  * 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).
9264  * 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
9265  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
9266  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
9267  * \param desc is the descending connectivity 3D->3DSurf
9268  * \param descIndx is the descending connectivity index 3D->3DSurf
9269  */
9270 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
9271                                                   const int *desc, const int *descIndx,
9272                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
9273 {
9274   checkFullyDefined();
9275   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9276     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
9277   const int *nodal3D=_nodal_connec->getConstPointer();
9278   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
9279   int nbOfCells=getNumberOfCells();
9280   for(int i=0;i<nbOfCells;i++)
9281     {
9282       std::map<int, std::set<int> > m;
9283       int offset=descIndx[i];
9284       int nbOfFaces=descIndx[i+1]-offset;
9285       int start=-1;
9286       int end=-1;
9287       for(int j=0;j<nbOfFaces;j++)
9288         {
9289           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
9290           if(p.first!=-1 && p.second!=-1)
9291             {
9292               if(p.first!=-2)
9293                 {
9294                   start=p.first; end=p.second;
9295                   m[p.first].insert(p.second);
9296                   m[p.second].insert(p.first);
9297                 }
9298               else
9299                 {
9300                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
9301                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
9302                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
9303                   INTERP_KERNEL::NormalizedCellType cmsId;
9304                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
9305                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
9306                   for(unsigned k=0;k<nbOfNodesSon;k++)
9307                     {
9308                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
9309                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
9310                     }
9311                 }
9312             }
9313         }
9314       if(m.empty())
9315         continue;
9316       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
9317       int prev=end;
9318       while(end!=start)
9319         {
9320           std::map<int, std::set<int> >::const_iterator it=m.find(start);
9321           const std::set<int>& s=(*it).second;
9322           std::set<int> s2; s2.insert(prev);
9323           std::set<int> s3;
9324           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
9325           if(s3.size()==1)
9326             {
9327               int val=*s3.begin();
9328               conn.push_back(start);
9329               prev=start;
9330               start=val;
9331             }
9332           else
9333             start=end;
9334         }
9335       conn.push_back(end);
9336       if(conn.size()>3)
9337         {
9338           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
9339           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
9340           cellIds->pushBackSilent(i);
9341         }
9342     }
9343 }
9344
9345 /*!
9346  * 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
9347  * 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
9348  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
9349  * 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
9350  * 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.
9351  * 
9352  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
9353  */
9354 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
9355 {
9356   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
9357   if(sz>=4)
9358     {
9359       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
9360       if(cm.getDimension()==2)
9361         {
9362           const int *node=nodalConnBg+1;
9363           int startNode=*node++;
9364           double refX=coords[2*startNode];
9365           for(;node!=nodalConnEnd;node++)
9366             {
9367               if(coords[2*(*node)]<refX)
9368                 {
9369                   startNode=*node;
9370                   refX=coords[2*startNode];
9371                 }
9372             }
9373           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
9374           refX=1e300;
9375           double tmp1;
9376           double tmp2[2];
9377           double angle0=-M_PI/2;
9378           //
9379           int nextNode=-1;
9380           int prevNode=-1;
9381           double resRef;
9382           double angleNext=0.;
9383           while(nextNode!=startNode)
9384             {
9385               nextNode=-1;
9386               resRef=1e300;
9387               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
9388                 {
9389                   if(*node!=tmpOut.back() && *node!=prevNode)
9390                     {
9391                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
9392                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
9393                       double res;
9394                       if(angleM<=angle0)
9395                         res=angle0-angleM;
9396                       else
9397                         res=angle0-angleM+2.*M_PI;
9398                       if(res<resRef)
9399                         {
9400                           nextNode=*node;
9401                           resRef=res;
9402                           angleNext=angleM;
9403                         }
9404                     }
9405                 }
9406               if(nextNode!=startNode)
9407                 {
9408                   angle0=angleNext-M_PI;
9409                   if(angle0<-M_PI)
9410                     angle0+=2*M_PI;
9411                   prevNode=tmpOut.back();
9412                   tmpOut.push_back(nextNode);
9413                 }
9414             }
9415           std::vector<int> tmp3(2*(sz-1));
9416           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
9417           std::copy(nodalConnBg+1,nodalConnEnd,it);
9418           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
9419             {
9420               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9421               return false;
9422             }
9423           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
9424             {
9425               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9426               return false;
9427             }
9428           else
9429             {
9430               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
9431               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
9432               return true;
9433             }
9434         }
9435       else
9436         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9437     }
9438   else
9439     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9440 }
9441
9442 /*!
9443  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
9444  * 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.
9445  * 
9446  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
9447  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
9448  * \param [in,out] arr array in which the remove operation will be done.
9449  * \param [in,out] arrIndx array in the remove operation will modify
9450  * \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])
9451  * \return true if \b arr and \b arrIndx have been modified, false if not.
9452  */
9453 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
9454 {
9455   if(!arrIndx || !arr)
9456     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
9457   if(offsetForRemoval<0)
9458     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
9459   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
9460   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
9461   int *arrIPtr=arrIndx->getPointer();
9462   *arrIPtr++=0;
9463   int previousArrI=0;
9464   const int *arrPtr=arr->getConstPointer();
9465   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
9466   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
9467     {
9468       if(*arrIPtr-previousArrI>offsetForRemoval)
9469         {
9470           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
9471             {
9472               if(s.find(*work)==s.end())
9473                 arrOut.push_back(*work);
9474             }
9475         }
9476       previousArrI=*arrIPtr;
9477       *arrIPtr=(int)arrOut.size();
9478     }
9479   if(arr->getNumberOfTuples()==(int)arrOut.size())
9480     return false;
9481   arr->alloc((int)arrOut.size(),1);
9482   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
9483   return true;
9484 }
9485
9486 /*!
9487  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9488  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
9489  * The selection of extraction is done standardly in new2old format.
9490  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9491  *
9492  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9493  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9494  * \param [in] arrIn arr origin array from which the extraction will be done.
9495  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9496  * \param [out] arrOut the resulting array
9497  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9498  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
9499  */
9500 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9501                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
9502 {
9503   if(!arrIn || !arrIndxIn)
9504     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
9505   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9506   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9507     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
9508   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
9509   const int *arrInPtr=arrIn->getConstPointer();
9510   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9511   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9512   if(nbOfGrps<0)
9513     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9514   int maxSizeOfArr=arrIn->getNumberOfTuples();
9515   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9516   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9517   arrIo->alloc((int)(sz+1),1);
9518   const int *idsIt=idsOfSelectBg;
9519   int *work=arrIo->getPointer();
9520   *work++=0;
9521   int lgth=0;
9522   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
9523     {
9524       if(*idsIt>=0 && *idsIt<nbOfGrps)
9525         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
9526       else
9527         {
9528           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9529           throw INTERP_KERNEL::Exception(oss.str().c_str());
9530         }
9531       if(lgth>=work[-1])
9532         *work=lgth;
9533       else
9534         {
9535           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
9536           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
9537           throw INTERP_KERNEL::Exception(oss.str().c_str());
9538         }
9539     }
9540   arro->alloc(lgth,1);
9541   work=arro->getPointer();
9542   idsIt=idsOfSelectBg;
9543   for(std::size_t i=0;i<sz;i++,idsIt++)
9544     {
9545       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
9546         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
9547       else
9548         {
9549           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
9550           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9551           throw INTERP_KERNEL::Exception(oss.str().c_str());
9552         }
9553     }
9554   arrOut=arro.retn();
9555   arrIndexOut=arrIo.retn();
9556 }
9557
9558 /*!
9559  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9560  * 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 ).
9561  * The selection of extraction is done standardly in new2old format.
9562  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9563  *
9564  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9565  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9566  * \param [in] arrIn arr origin array from which the extraction will be done.
9567  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9568  * \param [out] arrOut the resulting array
9569  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9570  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
9571  */
9572 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9573                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
9574 {
9575   if(!arrIn || !arrIndxIn)
9576     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
9577   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9578   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9579     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
9580   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
9581   const int *arrInPtr=arrIn->getConstPointer();
9582   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9583   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9584   if(nbOfGrps<0)
9585     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9586   int maxSizeOfArr=arrIn->getNumberOfTuples();
9587   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9588   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9589   arrIo->alloc((int)(sz+1),1);
9590   int idsIt=idsOfSelectStart;
9591   int *work=arrIo->getPointer();
9592   *work++=0;
9593   int lgth=0;
9594   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
9595     {
9596       if(idsIt>=0 && idsIt<nbOfGrps)
9597         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
9598       else
9599         {
9600           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9601           throw INTERP_KERNEL::Exception(oss.str().c_str());
9602         }
9603       if(lgth>=work[-1])
9604         *work=lgth;
9605       else
9606         {
9607           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
9608           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
9609           throw INTERP_KERNEL::Exception(oss.str().c_str());
9610         }
9611     }
9612   arro->alloc(lgth,1);
9613   work=arro->getPointer();
9614   idsIt=idsOfSelectStart;
9615   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
9616     {
9617       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
9618         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
9619       else
9620         {
9621           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
9622           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9623           throw INTERP_KERNEL::Exception(oss.str().c_str());
9624         }
9625     }
9626   arrOut=arro.retn();
9627   arrIndexOut=arrIo.retn();
9628 }
9629
9630 /*!
9631  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9632  * 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
9633  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9634  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9635  *
9636  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9637  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9638  * \param [in] arrIn arr origin array from which the extraction will be done.
9639  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9640  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
9641  * \param [in] srcArrIndex index array of \b srcArr
9642  * \param [out] arrOut the resulting array
9643  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9644  * 
9645  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9646  */
9647 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9648                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9649                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
9650 {
9651   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9652     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9653   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9654   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9655   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9656   std::vector<bool> v(nbOfTuples,true);
9657   int offset=0;
9658   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9659   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9660   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9661     {
9662       if(*it>=0 && *it<nbOfTuples)
9663         {
9664           v[*it]=false;
9665           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9666         }
9667       else
9668         {
9669           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9670           throw INTERP_KERNEL::Exception(oss.str().c_str());
9671         }
9672     }
9673   srcArrIndexPtr=srcArrIndex->getConstPointer();
9674   arrIo->alloc(nbOfTuples+1,1);
9675   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9676   const int *arrInPtr=arrIn->getConstPointer();
9677   const int *srcArrPtr=srcArr->getConstPointer();
9678   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9679   int *arroPtr=arro->getPointer();
9680   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9681     {
9682       if(v[ii])
9683         {
9684           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9685           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9686         }
9687       else
9688         {
9689           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9690           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9691           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9692         }
9693     }
9694   arrOut=arro.retn();
9695   arrIndexOut=arrIo.retn();
9696 }
9697
9698 /*!
9699  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9700  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9701  *
9702  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9703  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9704  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9705  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9706  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
9707  * \param [in] srcArrIndex index array of \b srcArr
9708  * 
9709  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9710  */
9711 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9712                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
9713 {
9714   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9715     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9716   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9717   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9718   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9719   int *arrInOutPtr=arrInOut->getPointer();
9720   const int *srcArrPtr=srcArr->getConstPointer();
9721   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9722     {
9723       if(*it>=0 && *it<nbOfTuples)
9724         {
9725           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9726             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9727           else
9728             {
9729               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] !";
9730               throw INTERP_KERNEL::Exception(oss.str().c_str());
9731             }
9732         }
9733       else
9734         {
9735           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9736           throw INTERP_KERNEL::Exception(oss.str().c_str());
9737         }
9738     }
9739 }
9740
9741 /*!
9742  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9743  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9744  * 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]].
9745  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9746  * A negative value in \b arrIn means that it is ignored.
9747  * 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.
9748  * 
9749  * \param [in] arrIn arr origin array from which the extraction will be done.
9750  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9751  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9752  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9753  */
9754 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9755 {
9756   int seed=0,nbOfDepthPeelingPerformed=0;
9757   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9758 }
9759
9760 /*!
9761  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9762  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9763  * 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]].
9764  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9765  * A negative value in \b arrIn means that it is ignored.
9766  * 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.
9767  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9768  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9769  * \param [in] arrIn arr origin array from which the extraction will be done.
9770  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9771  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9772  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9773  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9774  * \sa MEDCouplingUMesh::partitionBySpreadZone
9775  */
9776 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9777 {
9778   nbOfDepthPeelingPerformed=0;
9779   if(!arrIndxIn)
9780     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9781   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9782   if(nbOfTuples<=0)
9783     {
9784       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9785       return ret;
9786     }
9787   //
9788   std::vector<bool> fetched(nbOfTuples,false);
9789   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9790 }
9791
9792 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9793 {
9794   nbOfDepthPeelingPerformed=0;
9795   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9796     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9797   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9798   std::vector<bool> fetched2(nbOfTuples,false);
9799   int i=0;
9800   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9801     {
9802       if(*seedElt>=0 && *seedElt<nbOfTuples)
9803         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9804       else
9805         { 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()); }
9806     }
9807   const int *arrInPtr=arrIn->getConstPointer();
9808   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9809   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9810   std::vector<int> idsToFetch1(seedBg,seedEnd);
9811   std::vector<int> idsToFetch2;
9812   std::vector<int> *idsToFetch=&idsToFetch1;
9813   std::vector<int> *idsToFetchOther=&idsToFetch2;
9814   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9815     {
9816       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9817         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9818           if(!fetched[*it2])
9819             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9820       std::swap(idsToFetch,idsToFetchOther);
9821       idsToFetchOther->clear();
9822       nbOfDepthPeelingPerformed++;
9823     }
9824   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9825   i=0;
9826   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9827   int *retPtr=ret->getPointer();
9828   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9829     if(*it)
9830       *retPtr++=i;
9831   return ret.retn();
9832 }
9833
9834 /*!
9835  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9836  * 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
9837  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9838  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9839  *
9840  * \param [in] start begin of set of ids of the input extraction (included)
9841  * \param [in] end end of set of ids of the input extraction (excluded)
9842  * \param [in] step step of the set of ids in range mode.
9843  * \param [in] arrIn arr origin array from which the extraction will be done.
9844  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9845  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9846  * \param [in] srcArrIndex index array of \b srcArr
9847  * \param [out] arrOut the resulting array
9848  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9849  * 
9850  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9851  */
9852 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9853                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9854                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
9855 {
9856   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9857     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9858   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9859   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9860   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9861   int offset=0;
9862   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9863   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9864   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9865   int it=start;
9866   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9867     {
9868       if(it>=0 && it<nbOfTuples)
9869         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9870       else
9871         {
9872           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9873           throw INTERP_KERNEL::Exception(oss.str().c_str());
9874         }
9875     }
9876   srcArrIndexPtr=srcArrIndex->getConstPointer();
9877   arrIo->alloc(nbOfTuples+1,1);
9878   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9879   const int *arrInPtr=arrIn->getConstPointer();
9880   const int *srcArrPtr=srcArr->getConstPointer();
9881   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9882   int *arroPtr=arro->getPointer();
9883   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9884     {
9885       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9886       if(pos<0)
9887         {
9888           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9889           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9890         }
9891       else
9892         {
9893           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9894           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9895         }
9896     }
9897   arrOut=arro.retn();
9898   arrIndexOut=arrIo.retn();
9899 }
9900
9901 /*!
9902  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9903  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9904  *
9905  * \param [in] start begin of set of ids of the input extraction (included)
9906  * \param [in] end end of set of ids of the input extraction (excluded)
9907  * \param [in] step step of the set of ids in range mode.
9908  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9909  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9910  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9911  * \param [in] srcArrIndex index array of \b srcArr
9912  * 
9913  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9914  */
9915 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9916                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
9917 {
9918   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9919     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9920   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9921   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9922   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9923   int *arrInOutPtr=arrInOut->getPointer();
9924   const int *srcArrPtr=srcArr->getConstPointer();
9925   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9926   int it=start;
9927   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9928     {
9929       if(it>=0 && it<nbOfTuples)
9930         {
9931           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9932             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9933           else
9934             {
9935               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9936               throw INTERP_KERNEL::Exception(oss.str().c_str());
9937             }
9938         }
9939       else
9940         {
9941           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9942           throw INTERP_KERNEL::Exception(oss.str().c_str());
9943         }
9944     }
9945 }
9946
9947 /*!
9948  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9949  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9950  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9951  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9952  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9953  * 
9954  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9955  */
9956 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
9957 {
9958   checkFullyDefined();
9959   int mdim=getMeshDimension();
9960   int spaceDim=getSpaceDimension();
9961   if(mdim!=spaceDim)
9962     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9963   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9964   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9965   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9966   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9967   ret->setCoords(getCoords());
9968   ret->allocateCells((int)partition.size());
9969   //
9970   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9971     {
9972       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9973       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9974       switch(mdim)
9975       {
9976         case 2:
9977           cell=tmp->buildUnionOf2DMesh();
9978           break;
9979         case 3:
9980           cell=tmp->buildUnionOf3DMesh();
9981           break;
9982         default:
9983           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9984       }
9985
9986       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9987     }
9988   //
9989   ret->finishInsertingCells();
9990   return ret.retn();
9991 }
9992
9993 /*!
9994  * This method partitions \b this into contiguous zone.
9995  * This method only needs a well defined connectivity. Coordinates are not considered here.
9996  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9997  */
9998 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
9999 {
10000   int nbOfCellsCur=getNumberOfCells();
10001   std::vector<DataArrayInt *> ret;
10002   if(nbOfCellsCur<=0)
10003     return ret;
10004   DataArrayInt *neigh=0,*neighI=0;
10005   computeNeighborsOfCells(neigh,neighI);
10006   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
10007   std::vector<bool> fetchedCells(nbOfCellsCur,false);
10008   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
10009   int seed=0;
10010   while(seed<nbOfCellsCur)
10011     {
10012       int nbOfPeelPerformed=0;
10013       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
10014       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
10015     }
10016   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
10017     ret.push_back((*it).retn());
10018   return ret;
10019 }
10020
10021 /*!
10022  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
10023  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
10024  *
10025  * \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.
10026  * \return a newly allocated DataArrayInt to be managed by the caller.
10027  * \throw In case of \a code has not the right format (typically of size 3*n)
10028  */
10029 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
10030 {
10031   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
10032   std::size_t nb=code.size()/3;
10033   if(code.size()%3!=0)
10034     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
10035   ret->alloc((int)nb,2);
10036   int *retPtr=ret->getPointer();
10037   for(std::size_t i=0;i<nb;i++,retPtr+=2)
10038     {
10039       retPtr[0]=code[3*i+2];
10040       retPtr[1]=code[3*i+2]+code[3*i+1];
10041     }
10042   return ret.retn();
10043 }
10044
10045 /*!
10046  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
10047  * All cells in \a this are expected to be linear 3D cells.
10048  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
10049  * It leads to an increase to number of cells.
10050  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
10051  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
10052  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
10053  *
10054  * \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.
10055  *                      For all other cells, the splitting policy will be ignored.
10056  * \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. 
10057  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
10058  *          an id of old cell producing it. The caller is to delete this array using
10059  *         decrRef() as it is no more needed.
10060  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
10061  *
10062  * \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
10063  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
10064  * 
10065  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
10066  * \throw If \a this is not fully constituted with linear 3D cells.
10067  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
10068  */
10069 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
10070 {
10071   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
10072   checkConnectivityFullyDefined();
10073   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10074     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
10075   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
10076   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
10077   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
10078   int *retPt(ret->getPointer());
10079   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
10080   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
10081   const int *oldc(_nodal_connec->begin());
10082   const int *oldci(_nodal_connec_index->begin());
10083   const double *coords(_coords->begin());
10084   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
10085     {
10086       std::vector<int> a; std::vector<double> b;
10087       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
10088       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
10089       const int *aa(&a[0]);
10090       if(!b.empty())
10091         {
10092           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
10093             if(*it<0)
10094               *it=(-(*(it))-1+nbNodes);
10095           addPts->insertAtTheEnd(b.begin(),b.end());
10096           nbNodes+=(int)b.size()/3;
10097         }
10098       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
10099         newConn->insertAtTheEnd(aa,aa+4);
10100     }
10101   if(!addPts->empty())
10102     {
10103       addPts->rearrange(3);
10104       nbOfAdditionalPoints=addPts->getNumberOfTuples();
10105       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
10106       ret0->setCoords(addPts);
10107     }
10108   else
10109     {
10110       nbOfAdditionalPoints=0;
10111       ret0->setCoords(getCoords());
10112     }
10113   ret0->setNodalConnectivity(newConn);
10114   //
10115   ret->computeOffsets2();
10116   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
10117   return ret0.retn();
10118 }
10119
10120 /*!
10121  * 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). 
10122  *
10123  * \sa MEDCouplingUMesh::split2DCells
10124  */
10125 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
10126 {
10127   checkConnectivityFullyDefined();
10128   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
10129   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10130   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10131   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10132   int prevPosOfCi(ciPtr[0]);
10133   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10134     {
10135       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
10136       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
10137       for(int j=0;j<sz;j++)
10138         {
10139           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
10140           for(int k=0;k<sz2;k++)
10141             *cPtr++=subPtr[offset2+k];
10142           if(j!=sz-1)
10143             *cPtr++=oldConn[prevPosOfCi+j+2];
10144           deltaSz+=sz2;
10145         }
10146       prevPosOfCi=ciPtr[1];
10147       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10148     }
10149   if(c->end()!=cPtr)
10150     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
10151   _nodal_connec->decrRef();
10152   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
10153 }
10154
10155 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
10156 {
10157   if(id!=-1)
10158     return id;
10159   else
10160     {
10161       int ret(nodesCnter++);
10162       double newPt[2];
10163       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
10164       addCoo.insertAtTheEnd(newPt,newPt+2);
10165       return ret;
10166     }
10167 }
10168
10169 /// @cond INTERNAL
10170
10171 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)
10172 {
10173   int tmp[3];
10174   int trueStart(start>=0?start:nbOfEdges+start);
10175   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
10176   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
10177   if(linOrArc)
10178     {
10179       if(stp-start>1)
10180         {
10181           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10182           InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
10183           middles.push_back(tmp3+offset);
10184         }
10185       else
10186         middles.push_back(connBg[trueStart+nbOfEdges]);
10187     }
10188 }
10189
10190 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)
10191 {
10192   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
10193   newConnOfCell->pushBackSilent(tmpEnd);
10194   if(linOrArc)
10195     {
10196       if(stp-start>1)
10197         {
10198           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10199           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
10200           middles.push_back(tmp3+offset);
10201         }
10202       else
10203         middles.push_back(connBg[start+nbOfEdges]);
10204     }
10205 }
10206
10207 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)
10208 {
10209   if(linOrArc)
10210     {
10211       if(stp-start>1)
10212         {
10213           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
10214           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10215           InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
10216           middles.push_back(tmp3+offset);
10217         }
10218       else
10219         middles.push_back(connBg[start+nbOfEdges]);
10220     }
10221 }
10222
10223 /// @cond INTERNAL
10224
10225 /*!
10226  * 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 ) .
10227  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
10228  */
10229 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
10230 {
10231   std::size_t sz(std::distance(connBg,connEnd));
10232   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
10233     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
10234   sz--;
10235   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
10236   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
10237   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
10238   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
10239   INTERP_KERNEL::NormalizedCellType typeOfSon;
10240   std::vector<int> middles;
10241   bool ret(false);
10242   for(;nbOfHit<nbs;nbOfTurn++)
10243     {
10244       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
10245       std::map<INTERP_KERNEL::Node *,int> m;
10246       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
10247       posEndElt++;
10248       nbOfHit++;
10249       unsigned endI(nbs-nbOfHit);
10250       for(unsigned i=0;i<endI;i++)
10251         {
10252           cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
10253           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
10254           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
10255           bool isColinear(eint->areColinears());
10256           if(isColinear)
10257             {
10258               nbOfHit++;
10259               posEndElt++;
10260               ret=true;
10261             }
10262           delete eint;
10263           eCand->decrRef();
10264           if(!isColinear)
10265             {
10266               if(nbOfTurn==0)
10267                 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
10268                   unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
10269                   for(unsigned ii=0;ii<endII;ii++)
10270                     {
10271                       cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
10272                       eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
10273                       eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
10274                       isColinear=eint->areColinears();
10275                       if(isColinear)
10276                         {
10277                           nbOfHit++;
10278                           posBaseElt--;
10279                           ret=true;
10280                         }
10281                       delete eint;
10282                       eCand->decrRef();
10283                     }
10284                 }
10285               break;
10286             }
10287         }
10288       //push [posBaseElt,posEndElt) in newConnOfCell using e
10289       if(nbOfTurn==0)
10290         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10291       else if(nbOfHit!=nbs)
10292         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10293       else
10294         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10295       posBaseElt=posEndElt;
10296       for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it=m.begin();it!=m.end();it++)
10297         (*it).first->decrRef();
10298       e->decrRef();
10299     }
10300   if(!middles.empty())
10301     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
10302   return ret;
10303 }
10304
10305 /*!
10306  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
10307  *
10308  * \return  int - the number of new nodes created.
10309  * \sa MEDCouplingUMesh::split2DCells
10310  */
10311 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
10312 {
10313   checkCoherency();
10314   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
10315   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10316   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
10317   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10318   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
10319   const double *oldCoordsPtr(getCoords()->begin());
10320   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10321   int prevPosOfCi(ciPtr[0]);
10322   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10323     {
10324       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
10325       for(int j=0;j<sz;j++)
10326         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
10327       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
10328       for(int j=0;j<sz;j++)//loop over subedges of oldConn
10329         {
10330           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
10331           if(sz2==0)
10332             {
10333               if(j<sz-1)
10334                 cPtr[1]=oldConn[prevPosOfCi+2+j];
10335               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
10336               continue;
10337             }
10338           std::vector<INTERP_KERNEL::Node *> ns(3);
10339           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
10340           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
10341           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
10342           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
10343           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
10344             {
10345               cPtr[1]=subPtr[offset2+k];
10346               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
10347             }
10348           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
10349           if(j!=sz-1)
10350             { cPtr[1]=tmpEnd; }
10351           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
10352         }
10353       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
10354       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10355     }
10356   if(c->end()!=cPtr)
10357     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
10358   _nodal_connec->decrRef();
10359   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
10360   addCoo->rearrange(2);
10361   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
10362   setCoords(coo);
10363   return addCoo->getNumberOfTuples();
10364 }
10365
10366 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
10367     _own_cell(true),_cell_id(-1),_nb_cell(0)
10368 {
10369   if(mesh)
10370     {
10371       mesh->incrRef();
10372       _nb_cell=mesh->getNumberOfCells();
10373     }
10374 }
10375
10376 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
10377 {
10378   if(_mesh)
10379     _mesh->decrRef();
10380   if(_own_cell)
10381     delete _cell;
10382 }
10383
10384 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
10385     _own_cell(false),_cell_id(bg-1),
10386     _nb_cell(end)
10387 {
10388   if(mesh)
10389     mesh->incrRef();
10390 }
10391
10392 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
10393 {
10394   _cell_id++;
10395   if(_cell_id<_nb_cell)
10396     {
10397       _cell->next();
10398       return _cell;
10399     }
10400   else
10401     return 0;
10402 }
10403
10404 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
10405 {
10406   if(_mesh)
10407     _mesh->incrRef();
10408 }
10409
10410 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
10411 {
10412   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
10413 }
10414
10415 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
10416 {
10417   if(_mesh)
10418     _mesh->decrRef();
10419 }
10420
10421 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
10422     _itc(itc),
10423     _bg(bg),_end(end)
10424 {
10425   if(_mesh)
10426     _mesh->incrRef();
10427 }
10428
10429 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
10430 {
10431   if(_mesh)
10432     _mesh->decrRef();
10433 }
10434
10435 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
10436 {
10437   return _type;
10438 }
10439
10440 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
10441 {
10442   return _end-_bg;
10443 }
10444
10445 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
10446 {
10447   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
10448 }
10449
10450 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
10451 {
10452   if(mesh)
10453     {
10454       mesh->incrRef();
10455       _nb_cell=mesh->getNumberOfCells();
10456     }
10457 }
10458
10459 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
10460 {
10461   if(_mesh)
10462     _mesh->decrRef();
10463   delete _cell;
10464 }
10465
10466 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
10467 {
10468   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
10469   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
10470   if(_cell_id<_nb_cell)
10471     {
10472       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
10473       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
10474       int startId=_cell_id;
10475       _cell_id+=nbOfElems;
10476       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
10477     }
10478   else
10479     return 0;
10480 }
10481
10482 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
10483 {
10484   if(mesh)
10485     {
10486       _conn=mesh->getNodalConnectivity()->getPointer();
10487       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
10488     }
10489 }
10490
10491 void MEDCouplingUMeshCell::next()
10492 {
10493   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10494     {
10495       _conn+=_conn_lgth;
10496       _conn_indx++;
10497     }
10498   _conn_lgth=_conn_indx[1]-_conn_indx[0];
10499 }
10500
10501 std::string MEDCouplingUMeshCell::repr() const
10502 {
10503   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10504     {
10505       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
10506       oss << " : ";
10507       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
10508       return oss.str();
10509     }
10510   else
10511     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
10512 }
10513
10514 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
10515 {
10516   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10517     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
10518   else
10519     return INTERP_KERNEL::NORM_ERROR;
10520 }
10521
10522 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
10523 {
10524   lgth=_conn_lgth;
10525   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10526     return _conn;
10527   else
10528     return 0;
10529 }