Salome HOME
Avoid useless time stamp incrementation
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2020  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 (EDF R&D)
20
21 #include "MEDCouplingUMesh.txx"
22 #include "MEDCouplingCMesh.hxx"
23 #include "MEDCoupling1GTUMesh.hxx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "MEDCouplingSkyLineArray.hxx"
26 #include "CellModel.hxx"
27 #include "VolSurfUser.txx"
28 #include "InterpolationUtils.hxx"
29 #include "PointLocatorAlgos.txx"
30 #include "BBTree.txx"
31 #include "BBTreeDst.txx"
32 #include "SplitterTetra.hxx"
33 #include "DiameterCalculator.hxx"
34 #include "DirectedBoundingBox.hxx"
35 #include "InterpKernelMatrixTools.hxx"
36 #include "InterpKernelMeshQuality.hxx"
37 #include "InterpKernelCellSimplify.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelAutoPtr.hxx"
40 #include "InterpKernelGeo2DNode.hxx"
41 #include "InterpKernelGeo2DEdgeLin.hxx"
42 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
43 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
44 #include "OrientationInverter.hxx"
45 #include "MEDCouplingUMesh_internal.hxx"
46
47 #include <sstream>
48 #include <fstream>
49 #include <numeric>
50 #include <memory>
51 #include <cstring>
52 #include <limits>
53 #include <list>
54
55 using namespace MEDCoupling;
56
57 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
58
59 /// @cond INTERNAL
60
61 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_PENTA18, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
62 /// @endcond
63
64 MEDCouplingUMesh *MEDCouplingUMesh::New()
65 {
66   return new MEDCouplingUMesh;
67 }
68
69 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
70 {
71   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
72   ret->setName(meshName);
73   ret->setMeshDimension(meshDim);
74   return ret;
75 }
76
77 /*!
78  * Returns a new MEDCouplingUMesh which is a full copy of \a this one. No data is shared
79  * between \a this and the new mesh.
80  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
81  *          delete this mesh using decrRef() as it is no more needed.
82  */
83 MEDCouplingUMesh *MEDCouplingUMesh::deepCopy() const
84 {
85   return clone(true);
86 }
87
88
89 /*!
90  * Returns a new MEDCouplingUMesh which is a copy of \a this one.
91  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
92  * this mesh are shared by the new mesh.
93  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingMesh. The caller is to
94  *          delete this mesh using decrRef() as it is no more needed.
95  */
96 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
97 {
98   return new MEDCouplingUMesh(*this,recDeepCpy);
99 }
100
101 /*!
102  * This method behaves mostly like MEDCouplingUMesh::deepCopy method, except that only nodal connectivity arrays are deeply copied.
103  * The coordinates are shared between \a this and the returned instance.
104  *
105  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
106  * \sa MEDCouplingUMesh::deepCopy
107  */
108 MEDCouplingUMesh *MEDCouplingUMesh::deepCopyConnectivityOnly() const
109 {
110   checkConnectivityFullyDefined();
111   MCAuto<MEDCouplingUMesh> ret=clone(false);
112   MCAuto<DataArrayIdType> c(getNodalConnectivity()->deepCopy()),ci(getNodalConnectivityIndex()->deepCopy());
113   ret->setConnectivity(c,ci);
114   return ret.retn();
115 }
116
117 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
118 {
119   if(!other)
120     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
121   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
122   if(!otherC)
123     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
124   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
125   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
126 }
127
128 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
129 {
130   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
131   return ret;
132 }
133
134 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
135 {
136   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
137   ret.push_back(_nodal_connec);
138   ret.push_back(_nodal_connec_index);
139   return ret;
140 }
141
142 void MEDCouplingUMesh::updateTime() const
143 {
144   MEDCouplingPointSet::updateTime();
145   if(_nodal_connec)
146     {
147       updateTimeWith(*_nodal_connec);
148     }
149   if(_nodal_connec_index)
150     {
151       updateTimeWith(*_nodal_connec_index);
152     }
153 }
154
155 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
156 {
157 }
158
159 /*!
160  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
161  * then \a this mesh is most probably is writable, exchangeable and available for most
162  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
163  * this method to check that all is in order with \a this mesh.
164  *  \throw If the mesh dimension is not set.
165  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
166  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
167  *  \throw If the connectivity data array has more than one component.
168  *  \throw If the connectivity data array has a named component.
169  *  \throw If the connectivity index data array has more than one component.
170  *  \throw If the connectivity index data array has a named component.
171  */
172 void MEDCouplingUMesh::checkConsistencyLight() const
173 {
174   if(_mesh_dim<-1)
175     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
176   if(_mesh_dim!=-1)
177     MEDCouplingPointSet::checkConsistencyLight();
178   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
179     {
180       if(ToIdType(INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension())!=_mesh_dim)
181         {
182           std::ostringstream message;
183           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
184           throw INTERP_KERNEL::Exception(message.str().c_str());
185         }
186     }
187   if(_nodal_connec)
188     {
189       if(_nodal_connec->getNumberOfComponents()!=1)
190         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
191       if(_nodal_connec->getInfoOnComponent(0)!="")
192         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
193     }
194   else
195     if(_mesh_dim!=-1)
196       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
197   if(_nodal_connec_index)
198     {
199       if(_nodal_connec_index->getNumberOfComponents()!=1)
200         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
201       if(_nodal_connec_index->getInfoOnComponent(0)!="")
202         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
203     }
204   else
205     if(_mesh_dim!=-1)
206       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
207 }
208
209 /*!
210  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
211  * then \a this mesh is most probably is writable, exchangeable and available for all
212  * algorithms. <br> In addition to the checks performed by checkConsistencyLight(), this
213  * method thoroughly checks the nodal connectivity.
214  *  \param [in] eps - a not used parameter.
215  *  \throw If the mesh dimension is not set.
216  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
217  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
218  *  \throw If the connectivity data array has more than one component.
219  *  \throw If the connectivity data array has a named component.
220  *  \throw If the connectivity index data array has more than one component.
221  *  \throw If the connectivity index data array has a named component.
222  *  \throw If number of nodes defining an element does not correspond to the type of element.
223  *  \throw If the nodal connectivity includes an invalid node id.
224  */
225 void MEDCouplingUMesh::checkConsistency(double eps) const
226 {
227   checkConsistencyLight();
228   if(_mesh_dim==-1)
229     return ;
230   int meshDim=getMeshDimension();
231   mcIdType nbOfNodes=getNumberOfNodes();
232   mcIdType nbOfCells=getNumberOfCells();
233   const mcIdType *ptr=_nodal_connec->getConstPointer();
234   const mcIdType *ptrI=_nodal_connec_index->getConstPointer();
235   for(mcIdType i=0;i<nbOfCells;i++)
236     {
237       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
238       if(ToIdType(cm.getDimension())!=meshDim)
239         {
240           std::ostringstream oss;
241           oss << "MEDCouplingUMesh::checkConsistency : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
242           throw INTERP_KERNEL::Exception(oss.str());
243         }
244       mcIdType nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
245       if(!cm.isDynamic())
246         if(nbOfNodesInCell!=ToIdType(cm.getNumberOfNodes()))
247           {
248             std::ostringstream oss;
249             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
250             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
251             throw INTERP_KERNEL::Exception(oss.str());
252           }
253       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
254         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
255           {
256             std::ostringstream oss;
257             oss << "MEDCouplingUMesh::checkConsistency : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
258             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
259             throw INTERP_KERNEL::Exception(oss.str());
260           }
261       for(const mcIdType *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
262         {
263           mcIdType nodeId=*w;
264           if(nodeId>=0)
265             {
266               if(nodeId>=nbOfNodes)
267                 {
268                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
269                   throw INTERP_KERNEL::Exception(oss.str());
270                 }
271             }
272           else if(nodeId<-1)
273             {
274               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
275               throw INTERP_KERNEL::Exception(oss.str());
276             }
277           else
278             {
279               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
280                 {
281                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
282                   throw INTERP_KERNEL::Exception(oss.str());
283                 }
284             }
285         }
286     }
287 }
288
289 /*!
290  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
291  * elements contained in the mesh. For more info on the mesh dimension see
292  * \ref MEDCouplingUMeshPage.
293  *  \param [in] meshDim - a new mesh dimension.
294  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
295  */
296 void MEDCouplingUMesh::setMeshDimension(int meshDim)
297 {
298   if(meshDim<-1 || meshDim>3)
299     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
300   _mesh_dim=meshDim;
301   declareAsNew();
302 }
303
304 /*!
305  * Allocates memory to store an estimation of the given number of cells.
306  * The closer the estimation to the number of cells effectively inserted, the less need the library requires
307  * to reallocate memory. If the number of cells to be inserted is not known simply assign 0 to this parameter.
308  * If a nodal connectivity previously existed before the call of this method, it will be reset.
309  *
310  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
311  *
312  *  \if ENABLE_EXAMPLES
313  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
314  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
315  *  \endif
316  */
317 void MEDCouplingUMesh::allocateCells(mcIdType nbOfCells)
318 {
319   if(nbOfCells<0)
320     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
321   if(_nodal_connec_index)
322     {
323       _nodal_connec_index->decrRef();
324     }
325   if(_nodal_connec)
326     {
327       _nodal_connec->decrRef();
328     }
329   _nodal_connec_index=DataArrayIdType::New();
330   _nodal_connec_index->reserve(nbOfCells+1);
331   _nodal_connec_index->pushBackSilent(0);
332   _nodal_connec=DataArrayIdType::New();
333   _nodal_connec->reserve(2*nbOfCells);
334   _types.clear();
335   declareAsNew();
336 }
337
338 /*!
339  * Appends a cell to the connectivity array. For deeper understanding what is
340  * happening see \ref MEDCouplingUMeshNodalConnectivity.
341  *  \param [in] type - type of cell to add.
342  *  \param [in] size - number of nodes constituting this cell.
343  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
344  *
345  *  \if ENABLE_EXAMPLES
346  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
347  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
348  *  \endif
349  */
350 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, mcIdType size, const mcIdType *nodalConnOfCell)
351 {
352   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
353   if(_nodal_connec_index==0)
354     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
355   if(ToIdType(cm.getDimension())==_mesh_dim)
356     {
357       if(!cm.isDynamic())
358         if(size!=ToIdType(cm.getNumberOfNodes()))
359           {
360             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
361             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
362             throw INTERP_KERNEL::Exception(oss.str());
363           }
364       mcIdType idx=_nodal_connec_index->back();
365       mcIdType val=idx+size+1;
366       _nodal_connec_index->pushBackSilent(val);
367       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
368       _types.insert(type);
369     }
370   else
371     {
372       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
373       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
374       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
375       throw INTERP_KERNEL::Exception(oss.str());
376     }
377 }
378
379 /*!
380  * Compacts data arrays to release unused memory. This method is to be called after
381  * finishing cell insertion using \a this->insertNextCell().
382  *
383  *  \if ENABLE_EXAMPLES
384  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
385  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
386  *  \endif
387  */
388 void MEDCouplingUMesh::finishInsertingCells()
389 {
390   _nodal_connec->pack();
391   _nodal_connec_index->pack();
392   _nodal_connec->declareAsNew();
393   _nodal_connec_index->declareAsNew();
394   updateTime();
395 }
396
397 /*!
398  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
399  * Useful for python users.
400  */
401 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
402 {
403   return new MEDCouplingUMeshCellIterator(this);
404 }
405
406 /*!
407  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
408  * If \a this is not so that the cells are grouped by geo types, this method will throw an exception.
409  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
410  * Useful for python users.
411  */
412 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
413 {
414   if(!checkConsecutiveCellTypes())
415     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
416   return new MEDCouplingUMeshCellByTypeEntry(this);
417 }
418
419 /*!
420  * Returns a set of all cell types available in \a this mesh.
421  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
422  * \warning this method does not throw any exception even if \a this is not defined.
423  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
424  */
425 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
426 {
427   return _types;
428 }
429
430 /*!
431  * This method returns the sorted list of geometric types in \a this.
432  * 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
433  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
434  *
435  * \throw if connectivity in \a this is not correctly defined.
436  *
437  * \sa MEDCouplingMesh::getAllGeoTypes
438  */
439 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
440 {
441   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
442   checkConnectivityFullyDefined();
443   mcIdType nbOfCells=getNumberOfCells();
444   if(nbOfCells==0)
445     return ret;
446   if(getNodalConnectivityArrayLen()<1)
447     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
448   const mcIdType *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
449   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
450   for(mcIdType i=1;i<nbOfCells;i++,ci++)
451     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
452       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
453   return ret;
454 }
455
456 /*!
457  * This method is a method that compares \a this and \a other.
458  * This method compares \b all attributes, even names and component names.
459  */
460 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
461 {
462   if(!other)
463     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
464   std::ostringstream oss; oss.precision(15);
465   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
466   if(!otherC)
467     {
468       reason="mesh given in input is not castable in MEDCouplingUMesh !";
469       return false;
470     }
471   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
472     return false;
473   if(_mesh_dim!=otherC->_mesh_dim)
474     {
475       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
476       reason=oss.str();
477       return false;
478     }
479   if(_types!=otherC->_types)
480     {
481       oss << "umesh geometric type mismatch :\nThis geometric types are :";
482       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
483         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
484       oss << "\nOther geometric types are :";
485       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
486         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
487       reason=oss.str();
488       return false;
489     }
490   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
491     if(_nodal_connec==0 || otherC->_nodal_connec==0)
492       {
493         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
494         return false;
495       }
496   if(_nodal_connec!=otherC->_nodal_connec)
497     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
498       {
499         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
500         return false;
501       }
502   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
503     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
504       {
505         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
506         return false;
507       }
508   if(_nodal_connec_index!=otherC->_nodal_connec_index)
509     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
510       {
511         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
512         return false;
513       }
514   return true;
515 }
516
517 /*!
518  * Checks if data arrays of this mesh (node coordinates, nodal
519  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
520  * not considered.
521  *  \param [in] other - the mesh to compare with.
522  *  \param [in] prec - precision value used to compare node coordinates.
523  *  \return bool - \a true if the two meshes are same.
524  */
525 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
526 {
527   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
528   if(!otherC)
529     return false;
530   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
531     return false;
532   if(_mesh_dim!=otherC->_mesh_dim)
533     return false;
534   if(_types!=otherC->_types)
535     return false;
536   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
537     if(_nodal_connec==0 || otherC->_nodal_connec==0)
538       return false;
539   if(_nodal_connec!=otherC->_nodal_connec)
540     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
541       return false;
542   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
543     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
544       return false;
545   if(_nodal_connec_index!=otherC->_nodal_connec_index)
546     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
547       return false;
548   return true;
549 }
550
551 /*!
552  * Checks if \a this and \a other meshes are geometrically equivalent with high
553  * probability, else an exception is thrown. The meshes are considered equivalent if
554  * (1) meshes contain the same number of nodes and the same number of elements of the
555  * same types (2) three cells of the two meshes (first, last and middle) are based
556  * on coincident nodes (with a specified precision).
557  *  \param [in] other - the mesh to compare with.
558  *  \param [in] prec - the precision used to compare nodes of the two meshes.
559  *  \throw If the two meshes do not match.
560  */
561 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
562 {
563   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
564   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
565   if(!otherC)
566     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
567 }
568
569 /*!
570  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
571  * cells each node belongs to.
572  * \warning For speed reasons, this method does not check if node ids in the nodal
573  *          connectivity correspond to the size of node coordinates array.
574  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
575  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
576  *        dividing cell ids in \a revNodal into groups each referring to one
577  *        node. Its every element (except the last one) is an index pointing to the
578  *         first id of a group of cells. For example cells sharing the node #1 are
579  *        described by following range of indices:
580  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
581  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
582  *        Number of cells sharing the *i*-th node is
583  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
584  * \throw If the coordinates array is not set.
585  * \throw If the nodal connectivity of cells is not defined.
586  *
587  * \if ENABLE_EXAMPLES
588  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
589  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
590  * \endif
591  */
592 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayIdType *revNodal, DataArrayIdType *revNodalIndx) const
593 {
594   checkFullyDefined();
595   mcIdType nbOfNodes(getNumberOfNodes());
596   mcIdType *revNodalIndxPtr=(mcIdType *)malloc((nbOfNodes+1)*sizeof(mcIdType));
597   revNodalIndx->useArray(revNodalIndxPtr,true,DeallocType::C_DEALLOC,nbOfNodes+1,1);
598   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
599   const mcIdType *conn(_nodal_connec->begin()),*connIndex(_nodal_connec_index->begin());
600   mcIdType nbOfCells(getNumberOfCells()),nbOfEltsInRevNodal(0);
601   for(mcIdType eltId=0;eltId<nbOfCells;eltId++)
602     {
603       const mcIdType *strtNdlConnOfCurCell(conn+connIndex[eltId]+1),*endNdlConnOfCurCell(conn+connIndex[eltId+1]);
604       for(const mcIdType *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
605         if(*iter>=0)//for polyhedrons
606           {
607             nbOfEltsInRevNodal++;
608             revNodalIndxPtr[(*iter)+1]++;
609           }
610     }
611   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<mcIdType>());
612   mcIdType *revNodalPtr=(mcIdType *)malloc(nbOfEltsInRevNodal*sizeof(mcIdType));
613   revNodal->useArray(revNodalPtr,true,DeallocType::C_DEALLOC,nbOfEltsInRevNodal,1);
614   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
615   for(mcIdType eltId=0;eltId<nbOfCells;eltId++)
616     {
617       const mcIdType *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
618       const mcIdType *endNdlConnOfCurCell=conn+connIndex[eltId+1];
619       for(const mcIdType *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
620         if(*iter>=0)//for polyhedrons
621           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<mcIdType>(),-1))=eltId;
622     }
623 }
624
625 /*!
626  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
627  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
628  * describing correspondence between cells of \a this and the result meshes are
629  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
630  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
631  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
632  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh.
633  * \warning For speed reasons, this method does not check if node ids in the nodal
634  *          connectivity correspond to the size of node coordinates array.
635  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
636  *          to write this mesh to the MED file, its cells must be sorted using
637  *          sortCellsInMEDFileFrmt().
638  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
639  *         each cell of \a this mesh.
640  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
641  *        dividing cell ids in \a desc into groups each referring to one
642  *        cell of \a this mesh. Its every element (except the last one) is an index
643  *        pointing to the first id of a group of cells. For example cells of the
644  *        result mesh bounding the cell #1 of \a this mesh are described by following
645  *        range of indices:
646  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
647  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
648  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
649  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
650  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
651  *         by each cell of the result mesh.
652  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
653  *        in the result mesh,
654  *        dividing cell ids in \a revDesc into groups each referring to one
655  *        cell of the result mesh the same way as \a descIndx divides \a desc.
656  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
657  *        delete this mesh using decrRef() as it is no more needed.
658  *  \throw If the coordinates array is not set.
659  *  \throw If the nodal connectivity of cells is node defined.
660  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
661  *         revDescIndx == NULL.
662  *
663  *  \if ENABLE_EXAMPLES
664  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
665  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
666  *  \endif
667  * \sa buildDescendingConnectivity2()
668  */
669 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayIdType *desc, DataArrayIdType *descIndx, DataArrayIdType *revDesc, DataArrayIdType *revDescIndx) const
670 {
671   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
672 }
673
674 /*!
675  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
676  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
677  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
678  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
679  * \sa MEDCouplingUMesh::buildDescendingConnectivity
680  */
681 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayIdType *desc, DataArrayIdType *descIndx, DataArrayIdType *revDesc, DataArrayIdType *revDescIndx) const
682 {
683   checkFullyDefined();
684   if(getMeshDimension()!=3)
685     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
686   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
687 }
688
689 /*!
690  * This method computes the micro edges constituting each cell in \a this. Micro edge is an edge for non quadratic cells. Micro edge is an half edge for quadratic cells.
691  * This method works for both meshes with mesh dimension equal to 2 or 3. Dynamical cells are not supported (polygons, polyhedrons...)
692  * 
693  * \sa explode3DMeshTo1D, buildDescendingConnectiviy
694  */
695 MEDCouplingUMesh *MEDCouplingUMesh::explodeMeshIntoMicroEdges(DataArrayIdType *desc, DataArrayIdType *descIndx, DataArrayIdType *revDesc, DataArrayIdType *revDescIndx) const
696 {
697    checkFullyDefined();
698    switch(getMeshDimension())
699      {
700      case 2:
701        return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
702      case 3:
703        return buildDescendingConnectivityGen<MicroEdgesGenerator2D>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
704      default:
705        throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explodeMeshIntoMicroEdges : Only 2D and 3D supported !");
706      }
707 }
708
709 /*!
710  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
711  * this->getMeshDimension(), that bound cells of \a this mesh. In
712  * addition arrays describing correspondence between cells of \a this and the result
713  * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
714  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
715  *  mesh. This method differs from buildDescendingConnectivity() in that apart
716  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
717  * result meshes. So a positive id means that order of nodes in corresponding cells
718  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
719  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
720  * i.e. cell ids are one-based.
721  * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
722  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh.
723  * \warning For speed reasons, this method does not check if node ids in the nodal
724  *          connectivity correspond to the size of node coordinates array.
725  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
726  *          to write this mesh to the MED file, its cells must be sorted using
727  *          sortCellsInMEDFileFrmt().
728  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
729  *         each cell of \a this mesh.
730  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
731  *        dividing cell ids in \a desc into groups each referring to one
732  *        cell of \a this mesh. Its every element (except the last one) is an index
733  *        pointing to the first id of a group of cells. For example cells of the
734  *        result mesh bounding the cell #1 of \a this mesh are described by following
735  *        range of indices:
736  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
737  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
738  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
739  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
740  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
741  *         by each cell of the result mesh.
742  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
743  *        in the result mesh,
744  *        dividing cell ids in \a revDesc into groups each referring to one
745  *        cell of the result mesh the same way as \a descIndx divides \a desc.
746  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
747  *        shares the node coordinates array with \a this mesh. The caller is to
748  *        delete this mesh using decrRef() as it is no more needed.
749  *  \throw If the coordinates array is not set.
750  *  \throw If the nodal connectivity of cells is node defined.
751  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
752  *         revDescIndx == NULL.
753  *
754  *  \if ENABLE_EXAMPLES
755  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
756  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
757  *  \endif
758  * \sa buildDescendingConnectivity()
759  */
760 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayIdType *desc, DataArrayIdType *descIndx, DataArrayIdType *revDesc, DataArrayIdType *revDescIndx) const
761 {
762   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
763 }
764
765 /*!
766  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
767  * For speed reasons no check of this will be done. This method calls
768  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
769  * This method lists cell by cell in \b this which are its neighbors. To compute the result
770  * only connectivities are considered.
771  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
772  * The format of return is hence \ref numbering-indirect.
773  *
774  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
775  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
776  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
777  * is equal to the last values in \b neighborsIndx.
778  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
779  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
780  */
781 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayIdType *&neighbors, DataArrayIdType *&neighborsIndx) const
782 {
783   MCAuto<DataArrayIdType> desc=DataArrayIdType::New();
784   MCAuto<DataArrayIdType> descIndx=DataArrayIdType::New();
785   MCAuto<DataArrayIdType> revDesc=DataArrayIdType::New();
786   MCAuto<DataArrayIdType> revDescIndx=DataArrayIdType::New();
787   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
788   meshDM1=0;
789   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
790 }
791
792 void MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne(const DataArrayIdType *nodeNeigh, const DataArrayIdType *nodeNeighI, MCAuto<DataArrayIdType>& cellNeigh, MCAuto<DataArrayIdType>& cellNeighIndex) const
793 {
794   if(!nodeNeigh || !nodeNeighI)
795     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : null pointer !");
796   checkConsistencyLight();
797   nodeNeigh->checkAllocated(); nodeNeighI->checkAllocated();
798   nodeNeigh->checkNbOfComps(1,"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : node neigh");
799   nodeNeighI->checkNbOfComps(1,"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : node neigh index");
800   nodeNeighI->checkNbOfTuples(1+getNumberOfNodes(),"MEDCouplingUMesh::computeCellNeighborhoodFromNodesOne : invalid length");
801   mcIdType nbCells=getNumberOfCells();
802   const mcIdType *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin()),*ne(nodeNeigh->begin()),*nei(nodeNeighI->begin());
803   cellNeigh=DataArrayIdType::New(); cellNeigh->alloc(0,1); cellNeighIndex=DataArrayIdType::New(); cellNeighIndex->alloc(1,1); cellNeighIndex->setIJ(0,0,0);
804   for(mcIdType i=0;i<nbCells;i++)
805     {
806       std::set<mcIdType> s;
807       for(const mcIdType *it=c+ci[i]+1;it!=c+ci[i+1];it++)
808         if(*it>=0)
809           s.insert(ne+nei[*it],ne+nei[*it+1]);
810       s.erase(i);
811       cellNeigh->insertAtTheEnd(s.begin(),s.end());
812       cellNeighIndex->pushBackSilent(cellNeigh->getNumberOfTuples());
813     }
814 }
815
816 /*!
817  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
818  * of MEDCouplingUMesh::computeNeighborsOfCells.
819  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
820  * typically the case to extract a set a neighbours,
821  * excluding a set of meshdim-1 cells in input descending connectivity.
822  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
823  * the result of MEDCouplingUMesh::buildDescendingConnectivity.
824  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
825  * are considered.
826  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
827  *
828  * \param [in] desc descending connectivity array.
829  * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
830  * \param [in] revDesc reverse descending connectivity array.
831  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
832  * \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
833  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
834  * \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.
835  */
836 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayIdType *desc, const DataArrayIdType *descIndx, const DataArrayIdType *revDesc, const DataArrayIdType *revDescIndx,
837                                                   DataArrayIdType *&neighbors, DataArrayIdType *&neighborsIndx)
838 {
839   if(!desc || !descIndx || !revDesc || !revDescIndx)
840     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
841   const mcIdType *descPtr=desc->begin();
842   const mcIdType *descIPtr=descIndx->begin();
843   const mcIdType *revDescPtr=revDesc->begin();
844   const mcIdType *revDescIPtr=revDescIndx->begin();
845   //
846   mcIdType nbCells=descIndx->getNumberOfTuples()-1;
847   MCAuto<DataArrayIdType> out0=DataArrayIdType::New();
848   MCAuto<DataArrayIdType> out1=DataArrayIdType::New(); out1->alloc(nbCells+1,1);
849   mcIdType *out1Ptr=out1->getPointer();
850   *out1Ptr++=0;
851   out0->reserve(desc->getNumberOfTuples());
852   for(mcIdType i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
853     {
854       for(const mcIdType *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
855         {
856           std::set<mcIdType> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
857           s.erase(i);
858           out0->insertAtTheEnd(s.begin(),s.end());
859         }
860       *out1Ptr=out0->getNumberOfTuples();
861     }
862   neighbors=out0.retn();
863   neighborsIndx=out1.retn();
864 }
865
866 /*!
867  * Explodes \a this into edges whatever its dimension.
868  */
869 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::explodeIntoEdges(MCAuto<DataArrayIdType>& desc, MCAuto<DataArrayIdType>& descIndex, MCAuto<DataArrayIdType>& revDesc, MCAuto<DataArrayIdType>& revDescIndx) const
870 {
871   checkFullyDefined();
872   int mdim(getMeshDimension());
873   desc=DataArrayIdType::New(); descIndex=DataArrayIdType::New(); revDesc=DataArrayIdType::New(); revDescIndx=DataArrayIdType::New();
874   MCAuto<MEDCouplingUMesh> mesh1D;
875   switch(mdim)
876   {
877     case 3:
878       {
879         mesh1D=explode3DMeshTo1D(desc,descIndex,revDesc,revDescIndx);
880         break;
881       }
882     case 2:
883       {
884         mesh1D=buildDescendingConnectivity(desc,descIndex,revDesc,revDescIndx);
885         break;
886       }
887     default:
888       {
889         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2] !");
890       }
891   }
892   return mesh1D;
893 }
894
895 /*!
896  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
897  * For speed reasons no check of this will be done. This method calls
898  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
899  * This method lists node by node in \b this which are its neighbors. To compute the result
900  * only connectivities are considered.
901  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
902  *
903  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array
904  * is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
905  * parameter allows to select the right part in this array (\ref numbering-indirect).
906  * The number of tuples is equal to the last values in \b neighborsIndx.
907  * \param [out] neighborsIdx is an array of size this->getNumberOfCells()+1 newly allocated and should
908  * be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
909  *
910  * \sa MEDCouplingUMesh::computeEnlargedNeighborsOfNodes
911  */
912 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayIdType *&neighbors, DataArrayIdType *&neighborsIdx) const
913 {
914   checkFullyDefined();
915   mcIdType mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
916   MCAuto<DataArrayIdType> desc(DataArrayIdType::New()),descIndx(DataArrayIdType::New()),revDesc(DataArrayIdType::New()),revDescIndx(DataArrayIdType::New());
917   MCConstAuto<MEDCouplingUMesh> mesh1D;
918   switch(mdim)
919   {
920     case 3:
921       {
922         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
923         break;
924       }
925     case 2:
926       {
927         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
928         break;
929       }
930     case 1:
931       {
932         mesh1D.takeRef(this);
933         break;
934       }
935     default:
936       {
937         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
938       }
939   }
940   desc=DataArrayIdType::New(); descIndx=DataArrayIdType::New(); revDesc=0; revDescIndx=0;
941   mesh1D->getReverseNodalConnectivity(desc,descIndx);
942   MCAuto<DataArrayIdType> ret0(DataArrayIdType::New());
943   ret0->alloc(desc->getNumberOfTuples(),1);
944   mcIdType *r0Pt(ret0->getPointer());
945   const mcIdType *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
946   for(mcIdType i=0;i<nbNodes;i++,rni++)
947     {
948       for(const mcIdType *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
949         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
950     }
951   neighbors=ret0.retn();
952   neighborsIdx=descIndx.retn();
953 }
954
955 /*!
956  * Computes enlarged neighbors for each nodes in \a this. The behavior of this method is close to MEDCouplingUMesh::computeNeighborsOfNodes except that the neighborhood of each node is wider here.
957  * A node j is considered to be in the neighborhood of i if and only if there is a cell in \a this containing in its nodal connectivity both i and j.
958  * This method is useful to find ghost cells of a part of a mesh with a code based on fields on nodes.
959  *
960  * \sa MEDCouplingUMesh::computeNeighborsOfNodes
961  */
962 void MEDCouplingUMesh::computeEnlargedNeighborsOfNodes(MCAuto<DataArrayIdType> &neighbors, MCAuto<DataArrayIdType>& neighborsIdx) const
963 {
964   checkFullyDefined();
965   mcIdType nbOfNodes(getNumberOfNodes());
966   const mcIdType *conn(_nodal_connec->begin()),*connIndex(_nodal_connec_index->begin());
967   mcIdType nbOfCells=getNumberOfCells();
968   std::vector< std::set<mcIdType> > st0(nbOfNodes);
969   for(mcIdType eltId=0;eltId<nbOfCells;eltId++)
970     {
971       const mcIdType *strtNdlConnOfCurCell(conn+connIndex[eltId]+1),*endNdlConnOfCurCell(conn+connIndex[eltId+1]);
972       std::set<mcIdType> s(strtNdlConnOfCurCell,endNdlConnOfCurCell); s.erase(-1); //for polyhedrons
973       for(std::set<mcIdType>::const_iterator iter2=s.begin();iter2!=s.end();iter2++)
974         st0[*iter2].insert(s.begin(),s.end());
975     }
976   neighborsIdx=DataArrayIdType::New(); neighborsIdx->alloc(nbOfNodes+1,1); neighborsIdx->setIJ(0,0,0);
977   {
978     mcIdType *neighIdx(neighborsIdx->getPointer());
979     for(std::vector< std::set<mcIdType> >::const_iterator it=st0.begin();it!=st0.end();it++,neighIdx++)
980       {
981         if ((*it).empty())
982           neighIdx[1]=neighIdx[0];
983         else
984           neighIdx[1]=neighIdx[0]+ToIdType((*it).size())-1;
985       }
986   }
987   neighbors=DataArrayIdType::New(); neighbors->alloc(neighborsIdx->back(),1);
988   {
989     const mcIdType *neighIdx(neighborsIdx->begin());
990     mcIdType *neigh(neighbors->getPointer()),nodeId(0);
991     for(std::vector< std::set<mcIdType> >::const_iterator it=st0.begin();it!=st0.end();it++,neighIdx++,nodeId++)
992       {
993         std::set<mcIdType> s(*it); s.erase(nodeId);
994         std::copy(s.begin(),s.end(),neigh+*neighIdx);
995       }
996   }
997 }
998
999 /*!
1000  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1001  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1002  * array of cell ids. Pay attention that after conversion all algorithms work slower
1003  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1004  * conversion due presence of invalid ids in the array of cells to convert, as a
1005  * result \a this mesh contains some already converted elements. In this case the 2D
1006  * mesh remains valid but 3D mesh becomes \b inconsistent!
1007  *  \warning This method can significantly modify the order of geometric types in \a this,
1008  *          hence, to write this mesh to the MED file, its cells must be sorted using
1009  *          sortCellsInMEDFileFrmt().
1010  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1011  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1012  *         cellIdsToConvertBg.
1013  *  \throw If the coordinates array is not set.
1014  *  \throw If the nodal connectivity of cells is node defined.
1015  *  \throw If dimension of \a this mesh is not either 2 or 3.
1016  *
1017  *  \if ENABLE_EXAMPLES
1018  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1019  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1020  *  \endif
1021  */
1022 void MEDCouplingUMesh::convertToPolyTypes(const mcIdType *cellIdsToConvertBg, const mcIdType *cellIdsToConvertEnd)
1023 {
1024   checkFullyDefined();
1025   int dim=getMeshDimension();
1026   if(dim<2 || dim>3)
1027     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1028   mcIdType nbOfCells=getNumberOfCells();
1029   if(dim==2)
1030     {
1031       const mcIdType *connIndex=_nodal_connec_index->begin();
1032       mcIdType *conn=_nodal_connec->getPointer();
1033       for(const mcIdType *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1034         {
1035           if(*iter>=0 && *iter<nbOfCells)
1036             {
1037               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1038               if(!cm.isQuadratic())
1039                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1040               else
1041                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1042             }
1043           else
1044             {
1045               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1046               oss << " in range [0," << nbOfCells << ") !";
1047               throw INTERP_KERNEL::Exception(oss.str());
1048             }
1049         }
1050     }
1051   else
1052     {
1053       mcIdType *connIndex(_nodal_connec_index->getPointer());
1054       const mcIdType *connOld(_nodal_connec->getConstPointer());
1055       MCAuto<DataArrayIdType> connNew(DataArrayIdType::New()),connNewI(DataArrayIdType::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1056       std::vector<bool> toBeDone(nbOfCells,false);
1057       for(const mcIdType *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1058         {
1059           if(*iter>=0 && *iter<nbOfCells)
1060             toBeDone[*iter]=true;
1061           else
1062             {
1063               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1064               oss << " in range [0," << nbOfCells << ") !";
1065               throw INTERP_KERNEL::Exception(oss.str());
1066             }
1067         }
1068       for(mcIdType cellId=0;cellId<nbOfCells;cellId++)
1069         {
1070           mcIdType pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1071           mcIdType lgthOld(posP1-pos-1);
1072           if(toBeDone[cellId])
1073             {
1074               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1075               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1076               mcIdType *tmp(new mcIdType[nbOfFaces*lgthOld+1]);
1077               mcIdType *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1078               for(unsigned j=0;j<nbOfFaces;j++)
1079                 {
1080                   INTERP_KERNEL::NormalizedCellType type;
1081                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1082                   work+=offset;
1083                   *work++=-1;
1084                 }
1085               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1086               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1087               connNewI->pushBackSilent(connNewI->back()+ToIdType(newLgth));
1088               delete [] tmp;
1089             }
1090           else
1091             {
1092               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1093               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1094             }
1095         }
1096       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1097     }
1098   computeTypes();
1099 }
1100
1101 /*!
1102  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1103  * polyhedrons (if \a this is a 3D mesh).
1104  *  \warning As this method is purely for user-friendliness and no optimization is
1105  *          done to avoid construction of a useless vector, this method can be costly
1106  *          in memory.
1107  *  \throw If the coordinates array is not set.
1108  *  \throw If the nodal connectivity of cells is node defined.
1109  *  \throw If dimension of \a this mesh is not either 2 or 3.
1110  */
1111 void MEDCouplingUMesh::convertAllToPoly()
1112 {
1113   mcIdType nbOfCells=getNumberOfCells();
1114   std::vector<mcIdType> cellIds(nbOfCells);
1115   for(mcIdType i=0;i<nbOfCells;i++)
1116     cellIds[i]=i;
1117   convertToPolyTypes(&cellIds[0],&cellIds[0]+ToIdType(cellIds.size()));
1118 }
1119
1120 /*!
1121  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1122  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1123  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1124  * base facet of the volume and the second half of nodes describes an opposite facet
1125  * having the same number of nodes as the base one. This method converts such
1126  * connectivity to a valid polyhedral format where connectivity of each facet is
1127  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1128  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1129  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1130  * a correct orientation of the first facet of a polyhedron, else orientation of a
1131  * corrected cell is reverse.<br>
1132  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1133  * it releases the user from boring description of polyhedra connectivity in the valid
1134  * format.
1135  *  \throw If \a this->getMeshDimension() != 3.
1136  *  \throw If \a this->getSpaceDimension() != 3.
1137  *  \throw If the nodal connectivity of cells is not defined.
1138  *  \throw If the coordinates array is not set.
1139  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1140  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1141  *
1142  *  \if ENABLE_EXAMPLES
1143  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1144  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1145  *  \endif
1146  */
1147 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1148 {
1149   checkFullyDefined();
1150   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1151     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1152   mcIdType nbOfCells=getNumberOfCells();
1153   MCAuto<DataArrayIdType> newCi=DataArrayIdType::New();
1154   newCi->alloc(nbOfCells+1,1);
1155   mcIdType *newci=newCi->getPointer();
1156   const mcIdType *ci=_nodal_connec_index->getConstPointer();
1157   const mcIdType *c=_nodal_connec->getConstPointer();
1158   newci[0]=0;
1159   for(mcIdType i=0;i<nbOfCells;i++)
1160     {
1161       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1162       if(type==INTERP_KERNEL::NORM_POLYHED)
1163         {
1164           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1165             {
1166               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1167               throw INTERP_KERNEL::Exception(oss.str());
1168             }
1169           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1170           if(n2%2!=0)
1171             {
1172               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 !";
1173               throw INTERP_KERNEL::Exception(oss.str());
1174             }
1175           mcIdType n1=ToIdType(n2/2);
1176           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)
1177         }
1178       else
1179         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1180     }
1181   MCAuto<DataArrayIdType> newC=DataArrayIdType::New();
1182   newC->alloc(newci[nbOfCells],1);
1183   mcIdType *newc=newC->getPointer();
1184   for(mcIdType i=0;i<nbOfCells;i++)
1185     {
1186       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1187       if(type==INTERP_KERNEL::NORM_POLYHED)
1188         {
1189           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1190           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1191           *newc++=-1;
1192           for(std::size_t j=0;j<n1;j++)
1193             {
1194               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1195               newc[n1+5*j]=-1;
1196               newc[n1+5*j+1]=c[ci[i]+1+j];
1197               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1198               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1199               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1200             }
1201           newc+=n1*6;
1202         }
1203       else
1204         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1205     }
1206   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1207   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1208 }
1209
1210
1211 /*!
1212  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1213  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1214  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1215  *          to write this mesh to the MED file, its cells must be sorted using
1216  *          sortCellsInMEDFileFrmt().
1217  * \warning Cells (and most notably polyhedrons) must be correctly oriented for this to work
1218  *          properly. See orientCorrectlyPolyhedrons() and arePolyhedronsNotCorrectlyOriented().
1219  * \return \c true if at least one cell has been converted, \c false else. In the
1220  *         last case the nodal connectivity remains unchanged.
1221  * \throw If the coordinates array is not set.
1222  * \throw If the nodal connectivity of cells is not defined.
1223  * \throw If \a this->getMeshDimension() < 0.
1224  */
1225 bool MEDCouplingUMesh::unPolyze()
1226 {
1227   checkFullyDefined();
1228   int mdim=getMeshDimension();
1229   if(mdim<0)
1230     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1231   if(mdim<=1)
1232     return false;
1233   mcIdType nbOfCells=getNumberOfCells();
1234   if(nbOfCells<1)
1235     return false;
1236   mcIdType initMeshLgth=getNodalConnectivityArrayLen();
1237   mcIdType *conn=_nodal_connec->getPointer();
1238   mcIdType *index=_nodal_connec_index->getPointer();
1239   mcIdType posOfCurCell=0;
1240   mcIdType newPos=0;
1241   mcIdType lgthOfCurCell;
1242   bool ret=false;
1243   for(mcIdType i=0;i<nbOfCells;i++)
1244     {
1245       lgthOfCurCell=index[i+1]-posOfCurCell;
1246       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1247       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1248       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1249       mcIdType newLgth;
1250       if(cm.isDynamic())
1251         {
1252           switch(cm.getDimension())
1253           {
1254             case 2:
1255               {
1256                 INTERP_KERNEL::AutoPtr<mcIdType> tmp=new mcIdType[lgthOfCurCell-1];
1257                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(mcIdType *)tmp);
1258                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1259                 break;
1260               }
1261             case 3:
1262               {
1263                 mcIdType nbOfFaces,lgthOfPolyhConn;
1264                 INTERP_KERNEL::AutoPtr<mcIdType> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1265                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1266                 break;
1267               }
1268             case 1:
1269               {
1270                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1271                 break;
1272               }
1273           }
1274           ret=ret || (newType!=type);
1275           conn[newPos]=newType;
1276           newPos+=newLgth+1;
1277           posOfCurCell=index[i+1];
1278           index[i+1]=newPos;
1279         }
1280       else
1281         {
1282           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1283           newPos+=lgthOfCurCell;
1284           posOfCurCell+=lgthOfCurCell;
1285           index[i+1]=newPos;
1286         }
1287     }
1288   if(newPos!=initMeshLgth)
1289     _nodal_connec->reAlloc(newPos);
1290   if(ret)
1291     computeTypes();
1292   return ret;
1293 }
1294
1295 /*!
1296  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1297  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1298  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1299  *
1300  * \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
1301  *             precision.
1302  */
1303 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1304 {
1305   checkFullyDefined();
1306   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1307     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1308   MCAuto<DataArrayDouble> coords=getCoords()->deepCopy();
1309   coords->recenterForMaxPrecision(eps);
1310   //
1311   mcIdType nbOfCells=getNumberOfCells();
1312   const mcIdType *conn=_nodal_connec->getConstPointer();
1313   const mcIdType *index=_nodal_connec_index->getConstPointer();
1314   MCAuto<DataArrayIdType> connINew=DataArrayIdType::New();
1315   connINew->alloc(nbOfCells+1,1);
1316   mcIdType *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1317   MCAuto<DataArrayIdType> connNew=DataArrayIdType::New(); connNew->alloc(0,1);
1318   MCAuto<DataArrayIdType> E_Fi(DataArrayIdType::New()), E_F(DataArrayIdType::New()), F_Ei(DataArrayIdType::New()), F_E(DataArrayIdType::New());
1319   MCAuto<MEDCouplingUMesh> m_faces(buildDescendingConnectivity(E_F, E_Fi, F_E, F_Ei));
1320   bool changed=false;
1321   for(mcIdType i=0;i<nbOfCells;i++,connINewPtr++)
1322     {
1323       if(conn[index[i]]==ToIdType(INTERP_KERNEL::NORM_POLYHED))
1324         {
1325           SimplifyPolyhedronCell(eps,coords, i,connNew, m_faces, E_Fi, E_F, F_Ei, F_E);
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 the connectivity of \b this. The data array returned has to be dealt by the caller.
1338  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1339  * the format of the returned DataArrayIdType instance.
1340  *
1341  * \return a newly allocated DataArrayIdType sorted ascendingly of fetched node ids.
1342  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1343  */
1344 DataArrayIdType *MEDCouplingUMesh::computeFetchedNodeIds() const
1345 {
1346   checkConnectivityFullyDefined();
1347   const mcIdType *maxEltPt(std::max_element(_nodal_connec->begin(),_nodal_connec->end()));
1348   mcIdType maxElt(maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1);
1349   std::vector<bool> retS(maxElt,false);
1350   computeNodeIdsAlg(retS);
1351   return DataArrayIdType::BuildListOfSwitchedOn(retS);
1352 }
1353
1354 /*!
1355  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1356  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1357  */
1358 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1359 {
1360   mcIdType nbOfNodes=ToIdType(nodeIdsInUse.size()),
1361            nbOfCells=getNumberOfCells();
1362   const mcIdType *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1363   for(mcIdType i=0;i<nbOfCells;i++)
1364     for(mcIdType j=connIndex[i]+1;j<connIndex[i+1];j++)
1365       if(conn[j]>=0)
1366         {
1367           if(conn[j]<nbOfNodes)
1368             nodeIdsInUse[conn[j]]=true;
1369           else
1370             {
1371               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1372               throw INTERP_KERNEL::Exception(oss.str());
1373             }
1374         }
1375 }
1376
1377 /// @cond INTERNAL
1378
1379 struct MEDCouplingAccVisit
1380 {
1381   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1382   mcIdType operator()(mcIdType val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1383   mcIdType _new_nb_of_nodes;
1384 };
1385
1386 /// @endcond
1387
1388 /*!
1389  * Finds nodes not used in any cell and returns an array giving a new id to every node
1390  * by excluding the unused nodes, for which the array holds -1. The result array is
1391  * a mapping in "Old to New" mode.
1392  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1393  *  \return DataArrayIdType * - a new instance of DataArrayIdType. Its length is \a
1394  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1395  *          if the node is unused or a new id else. The caller is to delete this
1396  *          array using decrRef() as it is no more needed.
1397  *  \throw If the coordinates array is not set.
1398  *  \throw If the nodal connectivity of cells is not defined.
1399  *  \throw If the nodal connectivity includes an invalid id.
1400  *
1401  *  \if ENABLE_EXAMPLES
1402  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1403  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1404  *  \endif
1405  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1406  */
1407 DataArrayIdType *MEDCouplingUMesh::getNodeIdsInUse(mcIdType& nbrOfNodesInUse) const
1408 {
1409   nbrOfNodesInUse=-1;
1410   mcIdType nbOfNodes(getNumberOfNodes());
1411   MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
1412   ret->alloc(nbOfNodes,1);
1413   mcIdType *traducer=ret->getPointer();
1414   std::fill(traducer,traducer+nbOfNodes,-1);
1415   mcIdType nbOfCells=getNumberOfCells();
1416   const mcIdType *connIndex=_nodal_connec_index->getConstPointer();
1417   const mcIdType *conn=_nodal_connec->getConstPointer();
1418   for(mcIdType i=0;i<nbOfCells;i++)
1419     for(mcIdType j=connIndex[i]+1;j<connIndex[i+1];j++)
1420       if(conn[j]>=0)
1421         {
1422           if(conn[j]<nbOfNodes)
1423             traducer[conn[j]]=1;
1424           else
1425             {
1426               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1427               throw INTERP_KERNEL::Exception(oss.str());
1428             }
1429         }
1430   nbrOfNodesInUse=ToIdType(std::count(traducer,traducer+nbOfNodes,1));
1431   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1432   return ret.retn();
1433 }
1434
1435 /*!
1436  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1437  * For each cell in \b this the number of nodes constituting cell is computed.
1438  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1439  * So for pohyhedrons some nodes can be counted several times in the returned result.
1440  *
1441  * \return a newly allocated array
1442  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1443  */
1444 DataArrayIdType *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1445 {
1446   checkConnectivityFullyDefined();
1447   mcIdType nbOfCells=getNumberOfCells();
1448   MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
1449   ret->alloc(nbOfCells,1);
1450   mcIdType *retPtr=ret->getPointer();
1451   const mcIdType *conn=getNodalConnectivity()->getConstPointer();
1452   const mcIdType *connI=getNodalConnectivityIndex()->getConstPointer();
1453   for(mcIdType i=0;i<nbOfCells;i++,retPtr++)
1454     {
1455       if(conn[connI[i]]!=ToIdType(INTERP_KERNEL::NORM_POLYHED))
1456         *retPtr=connI[i+1]-connI[i]-1;
1457       else
1458         *retPtr=connI[i+1]-connI[i]-1-ToIdType(std::count(conn+connI[i]+1,conn+connI[i+1],-1));
1459     }
1460   return ret.retn();
1461 }
1462
1463 /*!
1464  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1465  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1466  *
1467  * \return DataArrayIdType * - new object to be deallocated by the caller.
1468  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1469  */
1470 DataArrayIdType *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1471 {
1472   checkConnectivityFullyDefined();
1473   mcIdType nbOfCells=getNumberOfCells();
1474   MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
1475   ret->alloc(nbOfCells,1);
1476   mcIdType *retPtr=ret->getPointer();
1477   const mcIdType *conn=getNodalConnectivity()->getConstPointer();
1478   const mcIdType *connI=getNodalConnectivityIndex()->getConstPointer();
1479   for(mcIdType i=0;i<nbOfCells;i++,retPtr++)
1480     {
1481       std::set<mcIdType> s(conn+connI[i]+1,conn+connI[i+1]);
1482       if(conn[connI[i]]!=ToIdType(INTERP_KERNEL::NORM_POLYHED))
1483         *retPtr=ToIdType(s.size());
1484       else
1485         {
1486           s.erase(-1);
1487           *retPtr=ToIdType(s.size());
1488         }
1489     }
1490   return ret.retn();
1491 }
1492
1493 /*!
1494  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1495  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1496  *
1497  * \return a newly allocated array
1498  */
1499 DataArrayIdType *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1500 {
1501   checkConnectivityFullyDefined();
1502   mcIdType nbOfCells=getNumberOfCells();
1503   MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
1504   ret->alloc(nbOfCells,1);
1505   mcIdType *retPtr=ret->getPointer();
1506   const mcIdType *conn=getNodalConnectivity()->getConstPointer();
1507   const mcIdType *connI=getNodalConnectivityIndex()->getConstPointer();
1508   for(mcIdType i=0;i<nbOfCells;i++,retPtr++,connI++)
1509     {
1510       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1511       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1512     }
1513   return ret.retn();
1514 }
1515
1516 /*!
1517  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1518  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1519  * array mean that the corresponding old node is no more used.
1520  *  \return DataArrayIdType * - a new instance of DataArrayIdType of length \a
1521  *           this->getNumberOfNodes() before call of this method. The caller is to
1522  *           delete this array using decrRef() as it is no more needed.
1523  *  \throw If the coordinates array is not set.
1524  *  \throw If the nodal connectivity of cells is not defined.
1525  *  \throw If the nodal connectivity includes an invalid id.
1526  *  \sa areAllNodesFetched
1527  *
1528  *  \if ENABLE_EXAMPLES
1529  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1530  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1531  *  \endif
1532  */
1533 DataArrayIdType *MEDCouplingUMesh::zipCoordsTraducer()
1534 {
1535   return MEDCouplingPointSet::zipCoordsTraducer();
1536 }
1537
1538 /*!
1539  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1540  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1541  */
1542 int MEDCouplingUMesh::AreCellsEqual(const mcIdType *conn, const mcIdType *connI, mcIdType cell1, mcIdType cell2, int compType)
1543 {
1544   switch(compType)
1545   {
1546     case 0:
1547       return AreCellsEqualPolicy0(conn,connI,cell1,cell2);
1548     case 1:
1549       return AreCellsEqualPolicy1(conn,connI,cell1,cell2);
1550     case 2:
1551       return AreCellsEqualPolicy2(conn,connI,cell1,cell2);
1552     case 3:
1553       return AreCellsEqualPolicy2NoType(conn,connI,cell1,cell2);
1554     case 7:
1555       return AreCellsEqualPolicy7(conn,connI,cell1,cell2);
1556   }
1557   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1558 }
1559
1560 /*!
1561  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1562  */
1563 int MEDCouplingUMesh::AreCellsEqualPolicy0(const mcIdType *conn, const mcIdType *connI, mcIdType cell1, mcIdType cell2)
1564 {
1565   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1566     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1567   return 0;
1568 }
1569
1570 /*!
1571  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1572  */
1573 int MEDCouplingUMesh::AreCellsEqualPolicy1(const mcIdType *conn, const mcIdType *connI, mcIdType cell1, mcIdType cell2)
1574 {
1575   mcIdType sz=connI[cell1+1]-connI[cell1];
1576   if(sz==connI[cell2+1]-connI[cell2])
1577     {
1578       if(conn[connI[cell1]]==conn[connI[cell2]])
1579         {
1580           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1581           unsigned dim=cm.getDimension();
1582           if(dim!=3)
1583             {
1584               if(dim!=1)
1585                 {
1586                   mcIdType sz1=2*(sz-1);
1587                   INTERP_KERNEL::AutoPtr<mcIdType> tmp=new mcIdType[sz1];
1588                   mcIdType *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(mcIdType *)tmp);
1589                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1590                   work=std::search((mcIdType *)tmp,(mcIdType *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1591                   return work!=tmp+sz1?1:0;
1592                 }
1593               else
1594                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1595             }
1596           else
1597             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy1 : not implemented yet for meshdim == 3 !");
1598         }
1599     }
1600   return 0;
1601 }
1602
1603 /*!
1604  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1605  */
1606 int MEDCouplingUMesh::AreCellsEqualPolicy2(const mcIdType *conn, const mcIdType *connI, mcIdType cell1, mcIdType cell2)
1607 {
1608   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1609     {
1610       if(conn[connI[cell1]]==conn[connI[cell2]])
1611         {
1612           std::set<mcIdType> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1613           std::set<mcIdType> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1614           return s1==s2?1:0;
1615         }
1616     }
1617   return 0;
1618 }
1619
1620 /*!
1621  * This method is less restrictive than AreCellsEqualPolicy2. Here the geometric type is absolutely not taken into account !
1622  */
1623 int MEDCouplingUMesh::AreCellsEqualPolicy2NoType(const mcIdType *conn, const mcIdType *connI, mcIdType cell1, mcIdType cell2)
1624 {
1625   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1626     {
1627       std::set<mcIdType> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1628       std::set<mcIdType> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1629       return s1==s2?1:0;
1630     }
1631   return 0;
1632 }
1633
1634 /*!
1635  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1636  */
1637 int MEDCouplingUMesh::AreCellsEqualPolicy7(const mcIdType *conn, const mcIdType *connI, mcIdType cell1, mcIdType cell2)
1638 {
1639   mcIdType sz=connI[cell1+1]-connI[cell1];
1640   if(sz==connI[cell2+1]-connI[cell2])
1641     {
1642       if(conn[connI[cell1]]==conn[connI[cell2]])
1643         {
1644           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1645           unsigned dim=cm.getDimension();
1646           if(dim!=3)
1647             {
1648               if(dim!=1)
1649                 {
1650                   mcIdType sz1=2*(sz-1);
1651                   INTERP_KERNEL::AutoPtr<mcIdType> tmp=new mcIdType[sz1];
1652                   mcIdType *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(mcIdType *)tmp);
1653                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1654                   work=std::search((mcIdType *)tmp,(mcIdType *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1655                   if(work!=tmp+sz1)
1656                     return 1;
1657                   else
1658                     {
1659                       std::reverse_iterator<mcIdType *> it1((mcIdType *)tmp+sz1);
1660                       std::reverse_iterator<mcIdType *> it2((mcIdType *)tmp);
1661                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1662                         return 2;
1663                       else
1664                         return 0;
1665                     }
1666
1667                   return work!=tmp+sz1?1:0;
1668                 }
1669               else
1670                 {//case of SEG2 and SEG3
1671                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1672                     return 1;
1673                   if(!cm.isQuadratic())
1674                     {
1675                       std::reverse_iterator<const mcIdType *> it1(conn+connI[cell1+1]);
1676                       std::reverse_iterator<const mcIdType *> it2(conn+connI[cell1]+1);
1677                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1678                         return 2;
1679                       return 0;
1680                     }
1681                   else
1682                     {
1683                       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])
1684                         return 2;
1685                       return 0;
1686                     }
1687                 }
1688             }
1689           else
1690             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqualPolicy7 : not implemented yet for meshdim == 3 !");
1691         }
1692     }
1693   return 0;
1694 }
1695
1696
1697 /*!
1698  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified by \a compType (see zipConnectivityTraducer).
1699  * This method keeps the coordinates of \a this. The comparison starts at rank \a startCellId cell id (included).
1700  * If \a startCellId is equal to 0 algorithm starts at cell #0 and for each cell candidates being searched have cell id higher than current cellId.
1701  * If \a startCellId is greater than 0 algorithm starts at cell #startCellId but for each cell all candidates are considered.
1702  * This method is time consuming.
1703  *
1704  * \param [in] compType input specifying the technique used to compare cells each other.
1705  *   - 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.
1706  *   - 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)
1707  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1708  *   - 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
1709  * can be used for users not sensitive to orientation of cell
1710  * \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.
1711  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1712  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1713  * \return the correspondence array old to new in a newly allocated array.
1714  *
1715  */
1716 void MEDCouplingUMesh::findCommonCells(int compType, mcIdType startCellId, DataArrayIdType *& commonCellsArr, DataArrayIdType *& commonCellsIArr) const
1717 {
1718   MCAuto<DataArrayIdType> revNodal=DataArrayIdType::New(),revNodalI=DataArrayIdType::New();
1719   getReverseNodalConnectivity(revNodal,revNodalI);
1720   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1721 }
1722
1723 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, mcIdType startCellId, const DataArrayIdType *nodal, const DataArrayIdType *nodalI, const DataArrayIdType *revNodal, const DataArrayIdType *revNodalI,
1724                                           DataArrayIdType *& commonCellsArr, DataArrayIdType *& commonCellsIArr)
1725 {
1726   MCAuto<DataArrayIdType> commonCells=DataArrayIdType::New(),commonCellsI=DataArrayIdType::New(); commonCells->alloc(0,1);
1727   mcIdType nbOfCells=nodalI->getNumberOfTuples()-1;
1728   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1729   const mcIdType *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1730   const mcIdType *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1731   std::vector<bool> isFetched(nbOfCells,false);
1732   if(startCellId==0)
1733     {
1734       for(mcIdType i=startCellId;i<nbOfCells;i++)
1735         {
1736           if(!isFetched[i])
1737             {
1738               const mcIdType *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<mcIdType>(),-1));
1739               std::vector<mcIdType> v,v2;
1740               if(connOfNode!=connPtr+connIPtr[i+1])
1741                 {
1742                   const mcIdType *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1743                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1744                   connOfNode++;
1745                 }
1746               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1747                 if(*connOfNode>=0)
1748                   {
1749                     v=v2;
1750                     const mcIdType *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1751                     std::vector<mcIdType>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1752                     v2.resize(std::distance(v2.begin(),it));
1753                   }
1754               if(v2.size()>1)
1755                 {
1756                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1757                     {
1758                       mcIdType pos=commonCellsI->back();
1759                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1760                       for(const mcIdType *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1761                         isFetched[*it]=true;
1762                     }
1763                 }
1764             }
1765         }
1766     }
1767   else
1768     {
1769       for(mcIdType i=startCellId;i<nbOfCells;i++)
1770         {
1771           if(!isFetched[i])
1772             {
1773               const mcIdType *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<mcIdType>(),-1));
1774               // v2 contains the result of successive intersections using rev nodal on on each node of cell #i
1775               std::vector<mcIdType> v,v2;
1776               if(connOfNode!=connPtr+connIPtr[i+1])
1777                 {
1778                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],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                     std::vector<mcIdType>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1786                     v2.resize(std::distance(v2.begin(),it));
1787                   }
1788               // v2 contains now candidates. Problem candidates are sorted using id rank.
1789               if(v2.size()>1)
1790                 {
1791                   if(v2[0]!=i)
1792                   {
1793                     auto it(std::find(v2.begin(),v2.end(),i));
1794                     std::swap(*v2.begin(),*it);
1795                   }
1796                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1797                     {
1798                       mcIdType newPos(commonCells->getNumberOfTuples());
1799                       mcIdType pos(commonCellsI->back());
1800                       std::sort(commonCells->getPointerSilent()+pos,commonCells->getPointerSilent()+newPos);
1801                       commonCellsI->pushBackSilent(newPos);
1802                       for(const mcIdType *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1803                         isFetched[*it]=true;
1804                     }
1805                 }
1806             }
1807         }
1808     }
1809   commonCellsArr=commonCells.retn();
1810   commonCellsIArr=commonCellsI.retn();
1811 }
1812
1813 /*!
1814  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1815  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1816  * than \a this->getNumberOfCells() in the returned array means that there is no
1817  * corresponding cell in \a this mesh.
1818  * It is expected that \a this and \a other meshes share the same node coordinates
1819  * array, if it is not so an exception is thrown.
1820  *  \param [in] other - the mesh to compare with.
1821  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1822  *         valid values [0,1,2], see zipConnectivityTraducer().
1823  *  \param [out] arr - a new instance of DataArrayIdType returning correspondence
1824  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1825  *         values. The caller is to delete this array using
1826  *         decrRef() as it is no more needed.
1827  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1828  *         mesh.
1829  *
1830  *  \if ENABLE_EXAMPLES
1831  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1832  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1833  *  \endif
1834  *  \sa checkDeepEquivalOnSameNodesWith()
1835  *  \sa checkGeoEquivalWith()
1836  */
1837 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayIdType *& arr) const
1838 {
1839   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1840   mcIdType nbOfCells=getNumberOfCells();
1841   static const int possibleCompType[]={0,1,2};
1842   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1843     {
1844       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1845       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1846       oss << " !";
1847       throw INTERP_KERNEL::Exception(oss.str());
1848     }
1849   //
1850   if(other->getNumberOfCells()==0)
1851   {
1852     MCAuto<DataArrayIdType> dftRet(DataArrayIdType::New()); dftRet->alloc(0,1); arr=dftRet.retn(); arr->setName(other->getName());
1853     return true;
1854   }
1855   DataArrayIdType *commonCells(nullptr),*commonCellsI(nullptr);
1856   mesh->findCommonCells(compType,nbOfCells,commonCells,commonCellsI);
1857   MCAuto<DataArrayIdType> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1858   mcIdType newNbOfCells=-1;
1859   MCAuto<DataArrayIdType> o2n = DataArrayIdType::ConvertIndexArrayToO2N(ToIdType(mesh->getNumberOfCells()),commonCells->begin(),commonCellsI->begin(),commonCellsI->end(),newNbOfCells);
1860   MCAuto<DataArrayIdType> p0(o2n->selectByTupleIdSafeSlice(0,nbOfCells,1));
1861   mcIdType maxPart(p0->getMaxValueInArray());
1862   bool ret(maxPart==newNbOfCells-1);
1863   MCAuto<DataArrayIdType> p1(p0->invertArrayO2N2N2O(newNbOfCells));
1864   // fill p1 array in case of presence of cells in other not in this
1865   mcIdType *pt(p1->getPointer());
1866   for(mcIdType i = maxPart ; i < newNbOfCells-1 ; ++i )
1867     pt[i+1] = i+1;
1868   //
1869   MCAuto<DataArrayIdType> p2(o2n->subArray(nbOfCells));
1870   p2->transformWithIndArr(p1->begin(),p1->end()); p2->setName(other->getName());
1871   arr = p2.retn();
1872   return ret;
1873 }
1874
1875 /*!
1876  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1877  * This method tries to determine if \b other is fully included in \b this.
1878  * The main difference is that this method is not expected to throw exception.
1879  * This method has two outputs :
1880  *
1881  * \param other other mesh
1882  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1883  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1884  */
1885 bool MEDCouplingUMesh::areCellsIncludedInPolicy7(const MEDCouplingUMesh *other, DataArrayIdType *& arr) const
1886 {
1887   MCAuto<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1888   DataArrayIdType *commonCells=0,*commonCellsI=0;
1889   mcIdType thisNbCells=getNumberOfCells();
1890   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1891   MCAuto<DataArrayIdType> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1892   const mcIdType *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1893   mcIdType otherNbCells=other->getNumberOfCells();
1894   MCAuto<DataArrayIdType> arr2=DataArrayIdType::New();
1895   arr2->alloc(otherNbCells,1);
1896   arr2->fillWithZero();
1897   mcIdType *arr2Ptr=arr2->getPointer();
1898   mcIdType nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1899   for(mcIdType i=0;i<nbOfCommon;i++)
1900     {
1901       mcIdType start=commonCellsPtr[commonCellsIPtr[i]];
1902       if(start<thisNbCells)
1903         {
1904           for(mcIdType j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1905             {
1906               mcIdType sig=commonCellsPtr[j]>0?1:-1;
1907               mcIdType val=std::abs(commonCellsPtr[j])-1;
1908               if(val>=thisNbCells)
1909                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1910             }
1911         }
1912     }
1913   arr2->setName(other->getName());
1914   if(arr2->presenceOfValue(0))
1915     return false;
1916   arr=arr2.retn();
1917   return true;
1918 }
1919
1920 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1921 {
1922   if(!other)
1923     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1924   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1925   if(!otherC)
1926     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1927   std::vector<const MEDCouplingUMesh *> ms(2);
1928   ms[0]=this;
1929   ms[1]=otherC;
1930   return MergeUMeshesOnSameCoords(ms);
1931 }
1932
1933 /*!
1934  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1935  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1936  * cellIds is not given explicitly but by a range python like.
1937  *
1938  * \param start
1939  * \param end
1940  * \param step
1941  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see MEDCoupling::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
1942  * \return a newly allocated
1943  *
1944  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1945  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1946  */
1947 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfSlice(mcIdType start, mcIdType end, mcIdType step, bool keepCoords) const
1948 {
1949   if(getMeshDimension()!=-1)
1950     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelfSlice(start,end,step,keepCoords));
1951   else
1952     {
1953       mcIdType newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfSlice for -1 dimension mesh ");
1954       if(newNbOfCells!=1)
1955         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1956       if(start!=0)
1957         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1958       incrRef();
1959       return const_cast<MEDCouplingUMesh *>(this);
1960     }
1961 }
1962
1963 /*!
1964  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1965  * The result mesh shares or not the node coordinates array with \a this mesh depending
1966  * on \a keepCoords parameter.
1967  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1968  *           to write this mesh to the MED file, its cells must be sorted using
1969  *           sortCellsInMEDFileFrmt().
1970  *  \param [in] begin - an array of cell ids to include to the new mesh.
1971  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1972  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1973  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1974  *         by calling zipCoords().
1975  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
1976  *         to delete this mesh using decrRef() as it is no more needed.
1977  *  \throw If the coordinates array is not set.
1978  *  \throw If the nodal connectivity of cells is not defined.
1979  *  \throw If any cell id in the array \a begin is not valid.
1980  *
1981  *  \if ENABLE_EXAMPLES
1982  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1983  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1984  *  \endif
1985  */
1986 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const mcIdType *begin, const mcIdType *end, bool keepCoords) const
1987 {
1988   if(getMeshDimension()!=-1)
1989     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
1990   else
1991     {
1992       if(end-begin!=1)
1993         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1994       if(begin[0]!=0)
1995         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1996       incrRef();
1997       return const_cast<MEDCouplingUMesh *>(this);
1998     }
1999 }
2000
2001 /*!
2002  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2003  *
2004  * 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.
2005  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2006  * The number of cells of \b this will remain the same with this method.
2007  *
2008  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
2009  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
2010  * \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 ).
2011  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2012  */
2013 void MEDCouplingUMesh::setPartOfMySelf(const mcIdType *cellIdsBg, const mcIdType *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2014 {
2015   checkConnectivityFullyDefined();
2016   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2017   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2018     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2019   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2020     {
2021       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2022       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2023       throw INTERP_KERNEL::Exception(oss.str());
2024     }
2025   mcIdType nbOfCellsToModify( ToIdType((std::distance(cellIdsBg,cellIdsEnd))));
2026   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2027     {
2028       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2029       throw INTERP_KERNEL::Exception(oss.str());
2030     }
2031   mcIdType nbOfCells(getNumberOfCells());
2032   bool easyAssign(true);
2033   const mcIdType *connI(_nodal_connec_index->begin());
2034   const mcIdType *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->begin();
2035   for(const mcIdType *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2036     {
2037       if(*it>=0 && *it<nbOfCells)
2038         {
2039           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2040         }
2041       else
2042         {
2043           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2044           throw INTERP_KERNEL::Exception(oss.str());
2045         }
2046     }
2047   if(easyAssign)
2048     {
2049       DataArrayIdType::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2050       computeTypes();
2051     }
2052   else
2053     {
2054       DataArrayIdType *arrOut=0,*arrIOut=0;
2055       DataArrayIdType::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2056                                                arrOut,arrIOut);
2057       MCAuto<DataArrayIdType> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2058       setConnectivity(arrOut,arrIOut,true);
2059     }
2060 }
2061
2062 void MEDCouplingUMesh::setPartOfMySelfSlice(mcIdType start, mcIdType end, mcIdType step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2063 {
2064   checkConnectivityFullyDefined();
2065   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2066   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2067     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelfSlice : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2068   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2069     {
2070       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2071       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2072       throw INTERP_KERNEL::Exception(oss.str());
2073     }
2074   mcIdType nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelfSlice : ");
2075   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2076     {
2077       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2078       throw INTERP_KERNEL::Exception(oss.str());
2079     }
2080   mcIdType nbOfCells=getNumberOfCells();
2081   bool easyAssign=true;
2082   const mcIdType *connI=_nodal_connec_index->getConstPointer();
2083   const mcIdType *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2084   mcIdType it=start;
2085   for(mcIdType i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2086     {
2087       if(it>=0 && it<nbOfCells)
2088         {
2089           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2090         }
2091       else
2092         {
2093           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelfSlice : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2094           throw INTERP_KERNEL::Exception(oss.str());
2095         }
2096     }
2097   if(easyAssign)
2098     {
2099       DataArrayIdType::SetPartOfIndexedArraysSameIdxSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2100       computeTypes();
2101     }
2102   else
2103     {
2104       DataArrayIdType *arrOut=0,*arrIOut=0;
2105       DataArrayIdType::SetPartOfIndexedArraysSlice(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2106                                                 arrOut,arrIOut);
2107       MCAuto<DataArrayIdType> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2108       setConnectivity(arrOut,arrIOut,true);
2109     }
2110 }
2111
2112
2113 /*!
2114  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2115  * this->getMeshDimension(), that bound some cells of \a this mesh.
2116  * The cells of lower dimension to include to the result mesh are selected basing on
2117  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2118  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2119  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2120  * created mesh shares the node coordinates array with \a this mesh.
2121  *  \param [in] begin - the array of node ids.
2122  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2123  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2124  *         array \a begin are added, else cells whose any node is in the
2125  *         array \a begin are added.
2126  *  \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2127  *         to delete this mesh using decrRef() as it is no more needed.
2128  *  \throw If the coordinates array is not set.
2129  *  \throw If the nodal connectivity of cells is not defined.
2130  *  \throw If any node id in \a begin is not valid.
2131  *
2132  *  \if ENABLE_EXAMPLES
2133  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2134  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2135  *  \endif
2136  */
2137 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const mcIdType *begin, const mcIdType *end, bool fullyIn) const
2138 {
2139   MCAuto<DataArrayIdType> desc,descIndx,revDesc,revDescIndx;
2140   desc=DataArrayIdType::New(); descIndx=DataArrayIdType::New(); revDesc=DataArrayIdType::New(); revDescIndx=DataArrayIdType::New();
2141   MCAuto<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2142   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2143   return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2144 }
2145
2146 /*!
2147  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2148  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2149  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2150  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2151  *         by calling zipCoords().
2152  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2153  *         to delete this mesh using decrRef() as it is no more needed.
2154  *  \throw If the coordinates array is not set.
2155  *  \throw If the nodal connectivity of cells is not defined.
2156  *
2157  *  \if ENABLE_EXAMPLES
2158  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2159  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2160  *  \endif
2161  */
2162 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2163 {
2164   DataArrayIdType *desc=DataArrayIdType::New();
2165   DataArrayIdType *descIndx=DataArrayIdType::New();
2166   DataArrayIdType *revDesc=DataArrayIdType::New();
2167   DataArrayIdType *revDescIndx=DataArrayIdType::New();
2168   //
2169   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2170   revDesc->decrRef();
2171   desc->decrRef();
2172   descIndx->decrRef();
2173   mcIdType nbOfCells=meshDM1->getNumberOfCells();
2174   const mcIdType *revDescIndxC=revDescIndx->getConstPointer();
2175   std::vector<mcIdType> boundaryCells;
2176   for(mcIdType i=0;i<nbOfCells;i++)
2177     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2178       boundaryCells.push_back(i);
2179   revDescIndx->decrRef();
2180   MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2181   return ret;
2182 }
2183
2184 /*!
2185  * This method returns a newly created DataArrayIdType instance containing ids of cells located in boundary.
2186  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2187  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2188  */
2189 DataArrayIdType *MEDCouplingUMesh::findCellIdsOnBoundary() const
2190 {
2191   checkFullyDefined();
2192   MCAuto<DataArrayIdType> desc=DataArrayIdType::New();
2193   MCAuto<DataArrayIdType> descIndx=DataArrayIdType::New();
2194   MCAuto<DataArrayIdType> revDesc=DataArrayIdType::New();
2195   MCAuto<DataArrayIdType> revDescIndx=DataArrayIdType::New();
2196   //
2197   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2198   desc=(DataArrayIdType*)0; descIndx=(DataArrayIdType*)0;
2199   //
2200   MCAuto<DataArrayIdType> tmp=revDescIndx->deltaShiftIndex();
2201   MCAuto<DataArrayIdType> faceIds=tmp->findIdsEqual(1); tmp=(DataArrayIdType*)0;
2202   const mcIdType *revDescPtr=revDesc->getConstPointer();
2203   const mcIdType *revDescIndxPtr=revDescIndx->getConstPointer();
2204   mcIdType nbOfCells=getNumberOfCells();
2205   std::vector<bool> ret1(nbOfCells,false);
2206   mcIdType sz=0;
2207   for(const mcIdType *pt=faceIds->begin();pt!=faceIds->end();pt++)
2208     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2209       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2210   //
2211   DataArrayIdType *ret2=DataArrayIdType::New();
2212   ret2->alloc(sz,1);
2213   mcIdType *ret2Ptr=ret2->getPointer();
2214   sz=0;
2215   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2216     if(*it)
2217       *ret2Ptr++=sz;
2218   ret2->setName("BoundaryCells");
2219   return ret2;
2220 }
2221
2222 /*!
2223  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2224  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2225  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2226  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2227  *
2228  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2229  * This method also returns the cells ids set s1 which contains the cell ids in \b this for which one of the dim-1 constituent
2230  * equals a cell in \b otherDimM1OnSameCoords.
2231  *
2232  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2233  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2234  *
2235  * \param [in] otherDimM1OnSameCoords
2236  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2237  * \param [out] cellIdsRk1 a newly allocated array containing the cell ids of s1 \b indexed into the \b cellIdsRk0 subset. To get the absolute ids of s1, simply invoke
2238  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2239  */
2240 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayIdType *&cellIdsRk0, DataArrayIdType *&cellIdsRk1) const
2241 {
2242   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2243     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2244   checkConnectivityFullyDefined();
2245   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2246   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2247     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2248   MCAuto<DataArrayIdType> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2249   MCAuto<DataArrayIdType> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2250   MCAuto<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2251   MCAuto<DataArrayIdType> descThisPart=DataArrayIdType::New(),descIThisPart=DataArrayIdType::New(),revDescThisPart=DataArrayIdType::New(),revDescIThisPart=DataArrayIdType::New();
2252   MCAuto<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2253   const mcIdType *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2254   DataArrayIdType *idsOtherInConsti=0;
2255   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2256   MCAuto<DataArrayIdType> idsOtherInConstiAuto(idsOtherInConsti);
2257   if(!b)
2258     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2259   std::set<mcIdType> s1;
2260   for(const mcIdType *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2261     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2262   MCAuto<DataArrayIdType> s1arr_renum1=DataArrayIdType::New(); s1arr_renum1->alloc(s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2263   s1arr_renum1->sort();
2264   cellIdsRk0=s0arr.retn();
2265   //cellIdsRk1=s_renum1.retn();
2266   cellIdsRk1=s1arr_renum1.retn();
2267 }
2268
2269 /*!
2270  * 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
2271  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2272  *
2273  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2274  */
2275 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2276 {
2277   MCAuto<DataArrayIdType> desc=DataArrayIdType::New();
2278   MCAuto<DataArrayIdType> descIndx=DataArrayIdType::New();
2279   MCAuto<DataArrayIdType> revDesc=DataArrayIdType::New();
2280   MCAuto<DataArrayIdType> revDescIndx=DataArrayIdType::New();
2281   //
2282   MCAuto<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2283   revDesc=0; desc=0; descIndx=0;
2284   MCAuto<DataArrayIdType> revDescIndx2=revDescIndx->deltaShiftIndex();
2285   MCAuto<DataArrayIdType> part=revDescIndx2->findIdsEqual(1);
2286   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2287 }
2288
2289 /*!
2290  * Finds nodes lying on the boundary of \a this mesh.
2291  *  \return DataArrayIdType * - a new instance of DataArrayIdType holding ids of found
2292  *          nodes. The caller is to delete this array using decrRef() as it is no
2293  *          more needed.
2294  *  \throw If the coordinates array is not set.
2295  *  \throw If the nodal connectivity of cells is node defined.
2296  *
2297  *  \if ENABLE_EXAMPLES
2298  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2299  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2300  *  \endif
2301  */
2302 DataArrayIdType *MEDCouplingUMesh::findBoundaryNodes() const
2303 {
2304   MCAuto<MEDCouplingUMesh> skin=computeSkin();
2305   return skin->computeFetchedNodeIds();
2306 }
2307
2308 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2309 {
2310   incrRef();
2311   return const_cast<MEDCouplingUMesh *>(this);
2312 }
2313
2314 /*!
2315  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2316  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2317  * 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.
2318  * If a node is in the boundary of \b this \b and in the boundary of \b otherDimM1OnSameCoords this node is considered as needed to be duplicated.
2319  * 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.
2320  *
2321  * \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
2322  *             parameter is altered during the call.
2323  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2324  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2325  * \param [out] cellIdsNotModified cell ids mcIdType \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.
2326  *
2327  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2328  */
2329 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayIdType *& nodeIdsToDuplicate,
2330                                             DataArrayIdType *& cellIdsNeededToBeRenum, DataArrayIdType *& cellIdsNotModified) const
2331 {
2332   typedef MCAuto<DataArrayIdType> DAInt;
2333   typedef MCAuto<MEDCouplingUMesh> MCUMesh;
2334
2335   checkFullyDefined();
2336   otherDimM1OnSameCoords.checkFullyDefined();
2337   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2338     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2339   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2340     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2341
2342   // Checking star-shaped M1 group:
2343   DAInt dt0=DataArrayIdType::New(),dit0=DataArrayIdType::New(),rdt0=DataArrayIdType::New(),rdit0=DataArrayIdType::New();
2344   MCUMesh meshM2 = otherDimM1OnSameCoords.buildDescendingConnectivity(dt0, dit0, rdt0, rdit0);
2345   DAInt dsi = rdit0->deltaShiftIndex();
2346   DAInt idsTmp0 = dsi->findIdsNotInRange(-1, 3);
2347   if(idsTmp0->getNumberOfTuples())
2348     throw INTERP_KERNEL::Exception("MEDFileUMesh::buildInnerBoundaryAlongM1Group: group is too complex: some points (or edges) have more than two connected segments (or faces)!");
2349   dt0=0; dit0=0; rdt0=0; rdit0=0; idsTmp0=0;
2350
2351   // Get extreme nodes from the group (they won't be duplicated), ie nodes belonging to boundary cells of M1
2352   DAInt xtremIdsM2 = dsi->findIdsEqual(1); dsi = 0;
2353   MCUMesh meshM2Part = static_cast<MEDCouplingUMesh *>(meshM2->buildPartOfMySelf(xtremIdsM2->begin(), xtremIdsM2->end(),true));
2354   DAInt xtrem = meshM2Part->computeFetchedNodeIds();
2355   // Remove from the list points on the boundary of the M0 mesh (those need duplication!)
2356   dt0=DataArrayIdType::New(),dit0=DataArrayIdType::New(),rdt0=DataArrayIdType::New(),rdit0=DataArrayIdType::New();
2357   MCUMesh m0desc = buildDescendingConnectivity(dt0, dit0, rdt0, rdit0); dt0=0; dit0=0; rdt0=0;
2358   dsi = rdit0->deltaShiftIndex();
2359   DAInt boundSegs = dsi->findIdsEqual(1);   // boundary segs/faces of the M0 mesh
2360   MCUMesh m0descSkin = static_cast<MEDCouplingUMesh *>(m0desc->buildPartOfMySelf(boundSegs->begin(),boundSegs->end(), true));
2361   DAInt fNodes = m0descSkin->computeFetchedNodeIds();
2362   // In 3D, some points on the boundary of M0 still need duplication:
2363   DAInt notDup = 0;
2364   if (getMeshDimension() == 3)
2365     {
2366       DAInt dnu1=DataArrayIdType::New(), dnu2=DataArrayIdType::New(), dnu3=DataArrayIdType::New(), dnu4=DataArrayIdType::New();
2367       MCUMesh m0descSkinDesc = m0descSkin->buildDescendingConnectivity(dnu1, dnu2, dnu3, dnu4);
2368       dnu1=0;dnu2=0;dnu3=0;dnu4=0;
2369       DataArrayIdType * corresp=0;
2370       meshM2->areCellsIncludedIn(m0descSkinDesc,2,corresp);
2371       DAInt validIds = corresp->findIdsInRange(0, meshM2->getNumberOfCells());
2372       corresp->decrRef();
2373       if (validIds->getNumberOfTuples())
2374         {
2375           MCUMesh m1IntersecSkin = static_cast<MEDCouplingUMesh *>(m0descSkinDesc->buildPartOfMySelf(validIds->begin(), validIds->end(), true));
2376           DAInt notDuplSkin = m1IntersecSkin->findBoundaryNodes();
2377           DAInt fNodes1 = fNodes->buildSubstraction(notDuplSkin);
2378           notDup = xtrem->buildSubstraction(fNodes1);
2379         }
2380       else
2381         notDup = xtrem->buildSubstraction(fNodes);
2382     }
2383   else
2384     notDup = xtrem->buildSubstraction(fNodes);
2385
2386   // Now compute cells around group (i.e. cells where we will do the propagation to identify the two sub-sets delimited by the group)
2387   DAInt m1Nodes = otherDimM1OnSameCoords.computeFetchedNodeIds();
2388   DAInt dupl = m1Nodes->buildSubstraction(notDup);
2389   DAInt cellsAroundGroup = getCellIdsLyingOnNodes(dupl->begin(), dupl->end(), false);  // false= take cell in, even if not all nodes are in notDup
2390
2391   //
2392   MCUMesh m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellsAroundGroup->begin(),cellsAroundGroup->end(),true));
2393   mcIdType nCells2 = m0Part2->getNumberOfCells();
2394   DAInt desc00=DataArrayIdType::New(),descI00=DataArrayIdType::New(),revDesc00=DataArrayIdType::New(),revDescI00=DataArrayIdType::New();
2395   MCUMesh m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2396
2397   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2398   DataArrayIdType *tmp00=0,*tmp11=0;
2399   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2400   DAInt neighInit00(tmp00);
2401   DAInt neighIInit00(tmp11);
2402   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2403   DataArrayIdType *idsTmp=0;
2404   m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2405   DAInt ids(idsTmp);
2406   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2407   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2408   DataArrayIdType::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2409   DataArrayIdType *tmp0=0,*tmp1=0;
2410   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2411   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2412   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2413   DAInt neigh00(tmp0);
2414   DAInt neighI00(tmp1);
2415
2416   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2417   mcIdType seed = 0, nIter = 0;
2418   mcIdType nIterMax = nCells2+1; // Safety net for the loop
2419   DAInt hitCells = DataArrayIdType::New(); hitCells->alloc(nCells2);
2420   hitCells->fillWithValue(-1);
2421   DAInt cellsToModifyConn0_torenum = DataArrayIdType::New();
2422   cellsToModifyConn0_torenum->alloc(0,1);
2423   while (nIter < nIterMax)
2424     {
2425       DAInt t = hitCells->findIdsEqual(-1);
2426       if (!t->getNumberOfTuples())
2427         break;
2428       // Connex zone without the crack (to compute the next seed really)
2429       mcIdType dnu;
2430       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2431       mcIdType cnt(0);
2432       for (mcIdType * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2433         hitCells->setIJ(*ptr,0,1);
2434       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2435       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2436       cellsToModifyConn0_torenum = DataArrayIdType::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2437       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2438       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2439       DAInt nonHitCells = hitCells->findIdsEqual(-1);
2440       DAInt intersec = nonHitCells->buildIntersection(comple);
2441       if (intersec->getNumberOfTuples())
2442         { seed = intersec->getIJ(0,0); }
2443       else
2444         { break; }
2445       nIter++;
2446     }
2447   if (nIter >= nIterMax)
2448     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2449
2450   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2451   cellsToModifyConn0_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2452   cellsToModifyConn1_torenum->transformWithIndArr(cellsAroundGroup->begin(),cellsAroundGroup->end());
2453   //
2454   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2455   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2456   nodeIdsToDuplicate=dupl.retn();
2457 }
2458
2459 /*!
2460  * This method operates a modification of the connectivity and coords in \b this.
2461  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2462  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2463  * More explicitly the renumber array in nodes is not explicitly given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2464  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2465  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2466  *
2467  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2468  *
2469  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2470  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2471  */
2472 void MEDCouplingUMesh::duplicateNodes(const mcIdType *nodeIdsToDuplicateBg, const mcIdType *nodeIdsToDuplicateEnd)
2473 {
2474   mcIdType nbOfNodes=getNumberOfNodes();
2475   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2476   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2477 }
2478
2479 /*!
2480  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2481  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2482  *
2483  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2484  *
2485  * \sa renumberNodesInConn
2486  */
2487 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(mcIdType offset)
2488 {
2489   checkConnectivityFullyDefined();
2490   mcIdType *conn(getNodalConnectivity()->getPointer());
2491   const mcIdType *connIndex(getNodalConnectivityIndex()->getConstPointer());
2492   mcIdType nbOfCells=getNumberOfCells();
2493   for(mcIdType i=0;i<nbOfCells;i++)
2494     for(mcIdType iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2495       {
2496         mcIdType& node=conn[iconn];
2497         if(node>=0)//avoid polyhedron separator
2498           {
2499             node+=offset;
2500           }
2501       }
2502   _nodal_connec->declareAsNew();
2503   updateTime();
2504 }
2505
2506 /*!
2507  *  Same than renumberNodesInConn(const mcIdType *) except that here the format of old-to-new traducer is using map instead
2508  *  of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction
2509  *  of a big mesh.
2510  */
2511 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<mcIdType,mcIdType>& newNodeNumbersO2N)
2512 {
2513   this->renumberNodesInConnT< INTERP_KERNEL::HashMap<mcIdType,mcIdType> >(newNodeNumbersO2N);
2514 }
2515
2516 /*!
2517  *  Same than renumberNodesInConn(const mcIdType *) except that here the format of old-to-new traducer is using map instead
2518  *  of array. This method is dedicated for renumbering from a big set of nodes the a tiny set of nodes which is the case during extraction
2519  *  of a big mesh.
2520  */
2521 void MEDCouplingUMesh::renumberNodesInConn(const std::map<mcIdType,mcIdType>& newNodeNumbersO2N)
2522 {
2523   this->renumberNodesInConnT< std::map<mcIdType,mcIdType> >(newNodeNumbersO2N);
2524 }
2525
2526 /*!
2527  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2528  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2529  * This method is a generalization of shiftNodeNumbersInConn().
2530  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2531  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2532  *         this->getNumberOfNodes(), in "Old to New" mode.
2533  *         See \ref numbering for more info on renumbering modes.
2534  *  \throw If the nodal connectivity of cells is not defined.
2535  *
2536  *  \if ENABLE_EXAMPLES
2537  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2538  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2539  *  \endif
2540  */
2541 void MEDCouplingUMesh::renumberNodesInConn(const mcIdType *newNodeNumbersO2N)
2542 {
2543   checkConnectivityFullyDefined();
2544   mcIdType *conn=getNodalConnectivity()->getPointer();
2545   const mcIdType *connIndex=getNodalConnectivityIndex()->getConstPointer();
2546   mcIdType nbOfCells=getNumberOfCells();
2547   for(mcIdType i=0;i<nbOfCells;i++)
2548     for(mcIdType iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2549       {
2550         mcIdType& node=conn[iconn];
2551         if(node>=0)//avoid polyhedron separator
2552           {
2553             node=newNodeNumbersO2N[node];
2554           }
2555       }
2556   _nodal_connec->declareAsNew();
2557   updateTime();
2558 }
2559
2560 /*!
2561  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2562  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2563  * This method is an specialization of \ref MEDCoupling::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2564  *
2565  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2566  */
2567 void MEDCouplingUMesh::shiftNodeNumbersInConn(mcIdType delta)
2568 {
2569   checkConnectivityFullyDefined();
2570   mcIdType *conn=getNodalConnectivity()->getPointer();
2571   const mcIdType *connIndex=getNodalConnectivityIndex()->getConstPointer();
2572   mcIdType nbOfCells=getNumberOfCells();
2573   for(mcIdType i=0;i<nbOfCells;i++)
2574     for(mcIdType iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2575       {
2576         mcIdType& node=conn[iconn];
2577         if(node>=0)//avoid polyhedron separator
2578           {
2579             node+=delta;
2580           }
2581       }
2582   _nodal_connec->declareAsNew();
2583   updateTime();
2584 }
2585
2586 /*!
2587  * This method operates a modification of the connectivity in \b this.
2588  * 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.
2589  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2590  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2591  * More explicitly the renumber array in nodes is not explicitly given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2592  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2593  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2594  *
2595  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2596  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2597  *
2598  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2599  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2600  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2601  */
2602 void MEDCouplingUMesh::duplicateNodesInConn(const mcIdType *nodeIdsToDuplicateBg, const mcIdType *nodeIdsToDuplicateEnd, mcIdType offset)
2603 {
2604   checkConnectivityFullyDefined();
2605   std::map<mcIdType,mcIdType> m;
2606   mcIdType val=offset;
2607   for(const mcIdType *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2608     m[*work]=val;
2609   mcIdType *conn=getNodalConnectivity()->getPointer();
2610   const mcIdType *connIndex=getNodalConnectivityIndex()->getConstPointer();
2611   mcIdType nbOfCells=getNumberOfCells();
2612   for(mcIdType i=0;i<nbOfCells;i++)
2613     for(mcIdType iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2614       {
2615         mcIdType& node=conn[iconn];
2616         if(node>=0)//avoid polyhedron separator
2617           {
2618             std::map<mcIdType,mcIdType>::iterator it=m.find(node);
2619             if(it!=m.end())
2620               node=(*it).second;
2621           }
2622       }
2623   updateTime();
2624 }
2625
2626 /*!
2627  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2628  *
2629  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2630  * After the call of this method the number of cells remains the same as before.
2631  *
2632  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2633  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2634  * be strictly in [0;this->getNumberOfCells()).
2635  *
2636  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2637  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2638  * should be contained in[0;this->getNumberOfCells()).
2639  *
2640  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2641  * \param check
2642  */
2643 void MEDCouplingUMesh::renumberCells(const mcIdType *old2NewBg, bool check)
2644 {
2645   checkConnectivityFullyDefined();
2646   mcIdType nbCells=getNumberOfCells();
2647   const mcIdType *array=old2NewBg;
2648   if(check)
2649     array=DataArrayIdType::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2650   //
2651   const mcIdType *conn=_nodal_connec->getConstPointer();
2652   const mcIdType *connI=_nodal_connec_index->getConstPointer();
2653   MCAuto<DataArrayIdType> o2n=DataArrayIdType::New(); o2n->useArray(array,false,DeallocType::C_DEALLOC,nbCells,1);
2654   MCAuto<DataArrayIdType> n2o=o2n->invertArrayO2N2N2O(nbCells);
2655   const mcIdType *n2oPtr=n2o->begin();
2656   MCAuto<DataArrayIdType> newConn=DataArrayIdType::New();
2657   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2658   newConn->copyStringInfoFrom(*_nodal_connec);
2659   MCAuto<DataArrayIdType> newConnI=DataArrayIdType::New();
2660   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2661   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2662   //
2663   mcIdType *newC=newConn->getPointer();
2664   mcIdType *newCI=newConnI->getPointer();
2665   mcIdType loc=0;
2666   newCI[0]=loc;
2667   for(mcIdType i=0;i<nbCells;i++)
2668     {
2669       mcIdType pos=n2oPtr[i];
2670       mcIdType nbOfElts=connI[pos+1]-connI[pos];
2671       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2672       loc+=nbOfElts;
2673       newCI[i+1]=loc;
2674     }
2675   //
2676   setConnectivity(newConn,newConnI);
2677   if(check)
2678     free(const_cast<mcIdType *>(array));
2679 }
2680
2681 /*!
2682  * Finds cells whose bounding boxes intersect a given bounding box.
2683  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2684  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2685  *         zMax (if in 3D).
2686  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2687  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2688  *         extent of the bounding box of cell to produce an addition to this bounding box.
2689  *  \return DataArrayIdType * - a new instance of DataArrayIdType holding ids for found
2690  *         cells. The caller is to delete this array using decrRef() as it is no more
2691  *         needed.
2692  *  \throw If the coordinates array is not set.
2693  *  \throw If the nodal connectivity of cells is not defined.
2694  *
2695  *  \if ENABLE_EXAMPLES
2696  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2697  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2698  *  \endif
2699  */
2700 DataArrayIdType *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2701 {
2702   MCAuto<DataArrayIdType> elems=DataArrayIdType::New(); elems->alloc(0,1);
2703   if(getMeshDimension()==-1)
2704     {
2705       elems->pushBackSilent(0);
2706       return elems.retn();
2707     }
2708   int dim=getSpaceDimension();
2709   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2710   const mcIdType* conn      = getNodalConnectivity()->getConstPointer();
2711   const mcIdType* conn_index= getNodalConnectivityIndex()->getConstPointer();
2712   const double* coords = getCoords()->getConstPointer();
2713   mcIdType nbOfCells=getNumberOfCells();
2714   for ( mcIdType ielem=0; ielem<nbOfCells;ielem++ )
2715     {
2716       for (int i=0; i<dim; i++)
2717         {
2718           elem_bb[i*2]=std::numeric_limits<double>::max();
2719           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2720         }
2721
2722       for (mcIdType inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2723         {
2724           mcIdType node= conn[inode];
2725           if(node>=0)//avoid polyhedron separator
2726             {
2727               for (int idim=0; idim<dim; idim++)
2728                 {
2729                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2730                     {
2731                       elem_bb[idim*2] = coords[node*dim+idim] ;
2732                     }
2733                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2734                     {
2735                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2736                     }
2737                 }
2738             }
2739         }
2740       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2741         elems->pushBackSilent(ielem);
2742     }
2743   return elems.retn();
2744 }
2745
2746 /*!
2747  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2748  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2749  * added in 'elems' parameter.
2750  */
2751 DataArrayIdType *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2752 {
2753   MCAuto<DataArrayIdType> elems=DataArrayIdType::New(); elems->alloc(0,1);
2754   if(getMeshDimension()==-1)
2755     {
2756       elems->pushBackSilent(0);
2757       return elems.retn();
2758     }
2759   int dim=getSpaceDimension();
2760   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2761   const mcIdType* conn      = getNodalConnectivity()->getConstPointer();
2762   const mcIdType* conn_index= getNodalConnectivityIndex()->getConstPointer();
2763   const double* coords = getCoords()->getConstPointer();
2764   mcIdType nbOfCells=getNumberOfCells();
2765   for ( mcIdType ielem=0; ielem<nbOfCells;ielem++ )
2766     {
2767       for (int i=0; i<dim; i++)
2768         {
2769           elem_bb[i*2]=std::numeric_limits<double>::max();
2770           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2771         }
2772
2773       for (mcIdType inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2774         {
2775           mcIdType node= conn[inode];
2776           if(node>=0)//avoid polyhedron separator
2777             {
2778               for (int idim=0; idim<dim; idim++)
2779                 {
2780                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2781                     {
2782                       elem_bb[idim*2] = coords[node*dim+idim] ;
2783                     }
2784                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2785                     {
2786                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2787                     }
2788                 }
2789             }
2790         }
2791       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2792         elems->pushBackSilent(ielem);
2793     }
2794   return elems.retn();
2795 }
2796
2797 /*!
2798  * Returns a type of a cell by its id.
2799  *  \param [in] cellId - the id of the cell of interest.
2800  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2801  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2802  */
2803 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(mcIdType cellId) const
2804 {
2805   const mcIdType *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin());
2806   if(cellId<_nodal_connec_index->getNbOfElems()-1)
2807     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2808   else
2809     {
2810       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2811       throw INTERP_KERNEL::Exception(oss.str());
2812     }
2813 }
2814
2815 /*!
2816  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2817  * This method does not throw exception if geometric type \a type is not in \a this.
2818  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2819  * The coordinates array is not considered here.
2820  *
2821  * \param [in] type the geometric type
2822  * \return cell ids in this having geometric type \a type.
2823  */
2824 DataArrayIdType *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2825 {
2826
2827   MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
2828   ret->alloc(0,1);
2829   checkConnectivityFullyDefined();
2830   mcIdType nbCells=getNumberOfCells();
2831   int mdim=getMeshDimension();
2832   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2833   if(mdim!=ToIdType(cm.getDimension()))
2834     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2835   const mcIdType *ptI=_nodal_connec_index->getConstPointer();
2836   const mcIdType *pt=_nodal_connec->getConstPointer();
2837   for(mcIdType i=0;i<nbCells;i++)
2838     {
2839       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2840         ret->pushBackSilent(i);
2841     }
2842   return ret.retn();
2843 }
2844
2845 /*!
2846  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2847  */
2848 mcIdType MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2849 {
2850   const mcIdType *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin());
2851   mcIdType nbOfCells(getNumberOfCells()),ret(0);
2852   for(mcIdType i=0;i<nbOfCells;i++)
2853     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2854       ret++;
2855   return ret;
2856 }
2857
2858 /*!
2859  * Returns the nodal connectivity of a given cell.
2860  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2861  * all returned node ids can be used in getCoordinatesOfNode().
2862  *  \param [in] cellId - an id of the cell of interest.
2863  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2864  *         cleared before the appending.
2865  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2866  */
2867 void MEDCouplingUMesh::getNodeIdsOfCell(mcIdType cellId, std::vector<mcIdType>& conn) const
2868 {
2869   const mcIdType *ptI(_nodal_connec_index->begin()),*pt(_nodal_connec->begin());
2870   for(const mcIdType *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2871     if(*w>=0)
2872       conn.push_back(*w);
2873 }
2874
2875 std::string MEDCouplingUMesh::simpleRepr() const
2876 {
2877   static const char msg0[]="No coordinates specified !";
2878   std::ostringstream ret;
2879   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2880   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2881   int tmpp1,tmpp2;
2882   double tt=getTime(tmpp1,tmpp2);
2883   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2884   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2885   if(_mesh_dim>=-1)
2886     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2887   else
2888     { ret << " Mesh dimension has not been set or is invalid !"; }
2889   if(_coords!=0)
2890     {
2891       const int spaceDim=getSpaceDimension();
2892       ret << spaceDim << "\nInfo attached on space dimension : ";
2893       for(int i=0;i<spaceDim;i++)
2894         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2895       ret << "\n";
2896     }
2897   else
2898     ret << msg0 << "\n";
2899   ret << "Number of nodes : ";
2900   if(_coords!=0)
2901     ret << getNumberOfNodes() << "\n";
2902   else
2903     ret << msg0 << "\n";
2904   ret << "Number of cells : ";
2905   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2906     ret << getNumberOfCells() << "\n";
2907   else
2908     ret << "No connectivity specified !" << "\n";
2909   ret << "Cell types present : ";
2910   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2911     {
2912       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2913       ret << cm.getRepr() << " ";
2914     }
2915   ret << "\n";
2916   return ret.str();
2917 }
2918
2919 std::string MEDCouplingUMesh::advancedRepr() const
2920 {
2921   std::ostringstream ret;
2922   ret << simpleRepr();
2923   ret << "\nCoordinates array : \n___________________\n\n";
2924   if(_coords)
2925     _coords->reprWithoutNameStream(ret);
2926   else
2927     ret << "No array set !\n";
2928   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2929   reprConnectivityOfThisLL(ret);
2930   return ret.str();
2931 }
2932
2933 /*!
2934  * This method returns a C++ code that is a dump of \a this.
2935  * This method will throw if this is not fully defined.
2936  */
2937 std::string MEDCouplingUMesh::cppRepr() const
2938 {
2939   static const char coordsName[]="coords";
2940   static const char connName[]="conn";
2941   static const char connIName[]="connI";
2942   checkFullyDefined();
2943   std::ostringstream ret; ret << "// coordinates" << std::endl;
2944   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2945   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2946   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2947   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2948   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2949   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2950   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2951   return ret.str();
2952 }
2953
2954 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2955 {
2956   std::ostringstream ret;
2957   reprConnectivityOfThisLL(ret);
2958   return ret.str();
2959 }
2960
2961 /*!
2962  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsibility to deal with.
2963  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2964  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2965  * some algos).
2966  *
2967  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2968  * 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
2969  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2970  */
2971 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(std::size_t spaceDim) const
2972 {
2973   int mdim=getMeshDimension();
2974   if(mdim<0)
2975     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2976   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2977   MCAuto<DataArrayIdType> tmp1,tmp2;
2978   bool needToCpyCT=true;
2979   if(!_nodal_connec)
2980     {
2981       tmp1=DataArrayIdType::New(); tmp1->alloc(0,1);
2982       needToCpyCT=false;
2983     }
2984   else
2985     {
2986       tmp1=_nodal_connec;
2987       tmp1->incrRef();
2988     }
2989   if(!_nodal_connec_index)
2990     {
2991       tmp2=DataArrayIdType::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2992       needToCpyCT=false;
2993     }
2994   else
2995     {
2996       tmp2=_nodal_connec_index;
2997       tmp2->incrRef();
2998     }
2999   ret->setConnectivity(tmp1,tmp2,false);
3000   if(needToCpyCT)
3001     ret->_types=_types;
3002   if(!_coords)
3003     {
3004       MCAuto<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3005       ret->setCoords(coords);
3006     }
3007   else
3008     ret->setCoords(_coords);
3009   return ret.retn();
3010 }
3011
3012 mcIdType MEDCouplingUMesh::getNumberOfNodesInCell(mcIdType cellId) const
3013 {
3014   const mcIdType *ptI=_nodal_connec_index->getConstPointer();
3015   const mcIdType *pt=_nodal_connec->getConstPointer();
3016   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3017     return ptI[cellId+1]-ptI[cellId]-1;
3018   else
3019     return ToIdType(std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<mcIdType>(),-1)));
3020 }
3021
3022 /*!
3023  * Returns types of cells of the specified part of \a this mesh.
3024  * This method avoids computing sub-mesh explicitly to get its types.
3025  *  \param [in] begin - an array of cell ids of interest.
3026  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3027  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3028  *         describing the cell types.
3029  *  \throw If the coordinates array is not set.
3030  *  \throw If the nodal connectivity of cells is not defined.
3031  *  \sa getAllGeoTypes()
3032  */
3033 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const mcIdType *begin, const mcIdType *end) const
3034 {
3035   checkFullyDefined();
3036   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3037   const mcIdType *conn=_nodal_connec->getConstPointer();
3038   const mcIdType *connIndex=_nodal_connec_index->getConstPointer();
3039   for(const mcIdType *w=begin;w!=end;w++)
3040     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3041   return ret;
3042 }
3043
3044 /*!
3045  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3046  * Optionally updates
3047  * a set of types of cells constituting \a this mesh.
3048  * This method is for advanced users having prepared their connectivity before. For
3049  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3050  *  \param [in] conn - the nodal connectivity array.
3051  *  \param [in] connIndex - the nodal connectivity index array.
3052  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3053  *         mesh is updated.
3054  */
3055 void MEDCouplingUMesh::setConnectivity(DataArrayIdType *conn, DataArrayIdType *connIndex, bool isComputingTypes)
3056 {
3057   DataArrayIdType::SetArrayIn(conn,_nodal_connec);
3058   DataArrayIdType::SetArrayIn(connIndex,_nodal_connec_index);
3059   if(isComputingTypes)
3060     computeTypes();
3061   declareAsNew();
3062 }
3063
3064 /*!
3065  * Copy constructor. If 'deepCopy' is false \a this is a shallow copy of other.
3066  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3067  */
3068 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCpy):MEDCouplingPointSet(other,deepCpy),_mesh_dim(other._mesh_dim),
3069     _nodal_connec(0),_nodal_connec_index(0),
3070     _types(other._types)
3071 {
3072   if(other._nodal_connec)
3073     _nodal_connec=other._nodal_connec->performCopyOrIncrRef(deepCpy);
3074   if(other._nodal_connec_index)
3075     _nodal_connec_index=other._nodal_connec_index->performCopyOrIncrRef(deepCpy);
3076 }
3077
3078 MEDCouplingUMesh::~MEDCouplingUMesh()
3079 {
3080   if(_nodal_connec)
3081     _nodal_connec->decrRef();
3082   if(_nodal_connec_index)
3083     _nodal_connec_index->decrRef();
3084 }
3085
3086 /*!
3087  * Recomputes a set of cell types of \a this mesh. For more info see
3088  * \ref MEDCouplingUMeshNodalConnectivity.
3089  */
3090 void MEDCouplingUMesh::computeTypes()
3091 {
3092   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3093 }
3094
3095
3096 /*!
3097  * Returns a number of cells constituting \a this mesh.
3098  *  \return mcIdType - the number of cells in \a this mesh.
3099  *  \throw If the nodal connectivity of cells is not defined.
3100  */
3101 mcIdType MEDCouplingUMesh::getNumberOfCells() const
3102 {
3103   if(_nodal_connec_index)
3104     return _nodal_connec_index->getNumberOfTuples()-1;
3105   else
3106     if(_mesh_dim==-1)
3107       return 1;
3108     else
3109       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3110 }
3111
3112 /*!
3113  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3114  * mesh. For more info see \ref meshes.
3115  *  \return int - the dimension of \a this mesh.
3116  *  \throw If the mesh dimension is not defined using setMeshDimension().
3117  */
3118 int MEDCouplingUMesh::getMeshDimension() const
3119 {
3120   if(_mesh_dim<-1)
3121     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3122   return _mesh_dim;
3123 }
3124
3125 /*!
3126  * Returns a length of the nodal connectivity array.
3127  * This method is for test reason. Normally the integer returned is not useable by
3128  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3129  *  \return mcIdType - the length of the nodal connectivity array.
3130  */
3131 mcIdType MEDCouplingUMesh::getNodalConnectivityArrayLen() const
3132 {
3133   return _nodal_connec->getNbOfElems();
3134 }
3135
3136 /*!
3137  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3138  */
3139 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<mcIdType>& tinyInfo, std::vector<std::string>& littleStrings) const
3140 {
3141   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3142   tinyInfo.push_back(ToIdType(getMeshDimension()));
3143   tinyInfo.push_back(getNumberOfCells());
3144   if(_nodal_connec)
3145     tinyInfo.push_back(getNodalConnectivityArrayLen());
3146   else
3147     tinyInfo.push_back(-1);
3148 }
3149
3150 /*!
3151  * First step of unserialization process.
3152  */
3153 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<mcIdType>& tinyInfo) const
3154 {
3155   return tinyInfo[6]<=0;
3156 }
3157
3158 /*!
3159  * Second step of serialization process.
3160  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3161  * \param a1
3162  * \param a2
3163  * \param littleStrings
3164  */
3165 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<mcIdType>& tinyInfo, DataArrayIdType *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3166 {
3167   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3168   if(tinyInfo[5]!=-1)
3169     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3170 }
3171
3172 /*!
3173  * Third and final step of serialization process.
3174  */
3175 void MEDCouplingUMesh::serialize(DataArrayIdType *&a1, DataArrayDouble *&a2) const
3176 {
3177   MEDCouplingPointSet::serialize(a1,a2);
3178   if(getMeshDimension()>-1)
3179     {
3180       a1=DataArrayIdType::New();
3181       a1->alloc(getNodalConnectivityArrayLen()+getNumberOfCells()+1,1);
3182       mcIdType *ptA1=a1->getPointer();
3183       const mcIdType *conn=getNodalConnectivity()->getConstPointer();
3184       const mcIdType *index=getNodalConnectivityIndex()->getConstPointer();
3185       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3186       std::copy(conn,conn+getNodalConnectivityArrayLen(),ptA1);
3187     }
3188   else
3189     a1=0;
3190 }
3191
3192 /*!
3193  * Second and final unserialization process.
3194  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3195  */
3196 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<mcIdType>& tinyInfo, const DataArrayIdType *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3197 {
3198   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3199   setMeshDimension(FromIdType<int>(tinyInfo[5]));
3200   if(tinyInfo[7]!=-1)
3201     {
3202       // Connectivity
3203       const mcIdType *recvBuffer=a1->getConstPointer();
3204       MCAuto<DataArrayIdType> myConnecIndex=DataArrayIdType::New();
3205       myConnecIndex->alloc(tinyInfo[6]+1,1);
3206       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3207       MCAuto<DataArrayIdType> myConnec=DataArrayIdType::New();
3208       myConnec->alloc(tinyInfo[7],1);
3209       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3210       setConnectivity(myConnec, myConnecIndex);
3211     }
3212 }
3213
3214
3215
3216 /*!
3217  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3218  * mesh.<br>
3219  * For 1D cells, the returned field contains lengths.<br>
3220  * For 2D cells, the returned field contains areas.<br>
3221  * For 3D cells, the returned field contains volumes.
3222  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3223  *         orientation, i.e. the volume is always positive.
3224  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3225  *         and one time . The caller is to delete this field using decrRef() as it is no
3226  *         more needed.
3227  */
3228 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3229 {
3230   std::string name="MeasureOfMesh_";
3231   name+=getName();
3232   mcIdType nbelem=getNumberOfCells();
3233   MCAuto<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3234   field->setName(name);
3235   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3236   array->alloc(nbelem,1);
3237   double *area_vol=array->getPointer();
3238   field->setArray(array) ; array=0;
3239   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3240   field->synchronizeTimeWithMesh();
3241   if(getMeshDimension()!=-1)
3242     {
3243       mcIdType ipt;
3244       INTERP_KERNEL::NormalizedCellType type;
3245       int dim_space=getSpaceDimension();
3246       const double *coords=getCoords()->getConstPointer();
3247       const mcIdType *connec=getNodalConnectivity()->getConstPointer();
3248       const mcIdType *connec_index=getNodalConnectivityIndex()->getConstPointer();
3249       for(mcIdType iel=0;iel<nbelem;iel++)
3250         {
3251           ipt=connec_index[iel];
3252           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3253           area_vol[iel]=INTERP_KERNEL::computeVolSurfOfCell2<mcIdType,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[iel+1]-ipt-1,coords,dim_space);
3254         }
3255       if(isAbs)
3256         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3257     }
3258   else
3259     {
3260       area_vol[0]=std::numeric_limits<double>::max();
3261     }
3262   return field.retn();
3263 }
3264
3265 /*!
3266  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3267  * mesh.<br>
3268  * For 1D cells, the returned array contains lengths.<br>
3269  * For 2D cells, the returned array contains areas.<br>
3270  * For 3D cells, the returned array contains volumes.
3271  * This method avoids building explicitly a part of \a this mesh to perform the work.
3272  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3273  *         orientation, i.e. the volume is always positive.
3274  *  \param [in] begin - an array of cell ids of interest.
3275  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3276  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3277  *          delete this array using decrRef() as it is no more needed.
3278  *
3279  *  \if ENABLE_EXAMPLES
3280  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3281  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3282  *  \endif
3283  *  \sa getMeasureField()
3284  */
3285 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const mcIdType *begin, const mcIdType *end) const
3286 {
3287   std::string name="PartMeasureOfMesh_";
3288   name+=getName();
3289   std::size_t nbelem=std::distance(begin,end);
3290   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3291   array->setName(name);
3292   array->alloc(nbelem,1);
3293   double *area_vol=array->getPointer();
3294   if(getMeshDimension()!=-1)
3295     {
3296       mcIdType ipt;
3297       INTERP_KERNEL::NormalizedCellType type;
3298       int dim_space=getSpaceDimension();
3299       const double *coords=getCoords()->getConstPointer();
3300       const mcIdType *connec=getNodalConnectivity()->getConstPointer();
3301       const mcIdType *connec_index=getNodalConnectivityIndex()->getConstPointer();
3302       for(const mcIdType *iel=begin;iel!=end;iel++)
3303         {
3304           ipt=connec_index[*iel];
3305           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3306           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<mcIdType,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3307         }
3308       if(isAbs)
3309         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3310     }
3311   else
3312     {
3313       area_vol[0]=std::numeric_limits<double>::max();
3314     }
3315   return array.retn();
3316 }
3317
3318 /*!
3319  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3320  * \a this one. The returned field contains the dual cell volume for each corresponding
3321  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3322  *  the dual mesh in P1 sens of \a this.<br>
3323  * For 1D cells, the returned field contains lengths.<br>
3324  * For 2D cells, the returned field contains areas.<br>
3325  * For 3D cells, the returned field contains volumes.
3326  * This method is useful to check "P1*" conservative interpolators.
3327  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3328  *         orientation, i.e. the volume is always positive.
3329  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3330  *          nodes and one time. The caller is to delete this array using decrRef() as
3331  *          it is no more needed.
3332  */
3333 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3334 {
3335   MCAuto<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3336   std::string name="MeasureOnNodeOfMesh_";
3337   name+=getName();
3338   mcIdType nbNodes=getNumberOfNodes();
3339   MCAuto<DataArrayDouble> nnpc;
3340   {
3341     MCAuto<DataArrayIdType> tmp(computeNbOfNodesPerCell());
3342     nnpc=tmp->convertToDblArr();
3343   }
3344   std::for_each(nnpc->rwBegin(),nnpc->rwEnd(),[](double& v) { v=1./v; });
3345   const double *nnpcPtr(nnpc->begin());
3346   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3347   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3348   array->alloc(nbNodes,1);
3349   double *valsToFill=array->getPointer();
3350   std::fill(valsToFill,valsToFill+nbNodes,0.);
3351   const double *values=tmp->getArray()->getConstPointer();
3352   MCAuto<DataArrayIdType> da=DataArrayIdType::New();
3353   MCAuto<DataArrayIdType> daInd=DataArrayIdType::New();
3354   getReverseNodalConnectivity(da,daInd);
3355   const mcIdType *daPtr=da->getConstPointer();
3356   const mcIdType *daIPtr=daInd->getConstPointer();
3357   for(mcIdType i=0;i<nbNodes;i++)
3358     for(const mcIdType *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3359       valsToFill[i]+=nnpcPtr[*cell]*values[*cell];
3360   ret->setMesh(this);
3361   ret->setArray(array);
3362   return ret.retn();
3363 }
3364
3365 /*!
3366  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3367  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3368  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3369  * and are normalized.
3370  * <br> \a this can be either
3371  * - a  2D mesh in 2D or 3D space or
3372  * - an 1D mesh in 2D space.
3373  *
3374  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3375  *          cells and one time. The caller is to delete this field using decrRef() as
3376  *          it is no more needed.
3377  *  \throw If the nodal connectivity of cells is not defined.
3378  *  \throw If the coordinates array is not set.
3379  *  \throw If the mesh dimension is not set.
3380  *  \throw If the mesh and space dimension is not as specified above.
3381  */
3382 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3383 {
3384   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3385     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3386   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3387   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3388   mcIdType nbOfCells=getNumberOfCells();
3389   int nbComp=getMeshDimension()+1;
3390   array->alloc(nbOfCells,nbComp);
3391   double *vals=array->getPointer();
3392   const mcIdType *connI=_nodal_connec_index->getConstPointer();
3393   const mcIdType *conn=_nodal_connec->getConstPointer();
3394   const double *coords=_coords->getConstPointer();
3395   if(getMeshDimension()==2)
3396     {
3397       if(getSpaceDimension()==3)
3398         {
3399           MCAuto<DataArrayDouble> loc=computeCellCenterOfMass();
3400           const double *locPtr=loc->getConstPointer();
3401           for(mcIdType i=0;i<nbOfCells;i++,vals+=3)
3402             {
3403               mcIdType offset=connI[i];
3404               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3405               double n=INTERP_KERNEL::norm<3>(vals);
3406               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3407             }
3408         }
3409       else
3410         {
3411           MCAuto<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3412           const double *isAbsPtr=isAbs->getArray()->begin();
3413           for(mcIdType i=0;i<nbOfCells;i++,isAbsPtr++)
3414             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3415         }
3416     }
3417   else//meshdimension==1
3418     {
3419       double tmp[2];
3420       for(mcIdType i=0;i<nbOfCells;i++)
3421         {
3422           mcIdType offset=connI[i];
3423           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3424           double n=INTERP_KERNEL::norm<2>(tmp);
3425           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3426           *vals++=-tmp[1];
3427           *vals++=tmp[0];
3428         }
3429     }
3430   ret->setArray(array);
3431   ret->setMesh(this);
3432   ret->synchronizeTimeWithSupport();
3433   return ret.retn();
3434 }
3435
3436 /*!
3437  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3438  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3439  * and are normalized.
3440  * <br> \a this can be either
3441  * - a  2D mesh in 2D or 3D space or
3442  * - an 1D mesh in 2D space.
3443  *
3444  * This method avoids building explicitly a part of \a this mesh to perform the work.
3445  *  \param [in] begin - an array of cell ids of interest.
3446  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3447  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3448  *          cells and one time. The caller is to delete this field using decrRef() as
3449  *          it is no more needed.
3450  *  \throw If the nodal connectivity of cells is not defined.
3451  *  \throw If the coordinates array is not set.
3452  *  \throw If the mesh dimension is not set.
3453  *  \throw If the mesh and space dimension is not as specified above.
3454  *  \sa buildOrthogonalField()
3455  *
3456  *  \if ENABLE_EXAMPLES
3457  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3458  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3459  *  \endif
3460  */
3461 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const mcIdType *begin, const mcIdType *end) const
3462 {
3463   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3464     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3465   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3466   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3467   std::size_t nbelems=std::distance(begin,end);
3468   int nbComp=getMeshDimension()+1;
3469   array->alloc(nbelems,nbComp);
3470   double *vals=array->getPointer();
3471   const mcIdType *connI=_nodal_connec_index->getConstPointer();
3472   const mcIdType *conn=_nodal_connec->getConstPointer();
3473   const double *coords=_coords->getConstPointer();
3474   if(getMeshDimension()==2)
3475     {
3476       if(getSpaceDimension()==3)
3477         {
3478           MCAuto<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3479           const double *locPtr=loc->getConstPointer();
3480           for(const mcIdType *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3481             {
3482               mcIdType offset=connI[*i];
3483               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3484               double n=INTERP_KERNEL::norm<3>(vals);
3485               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3486             }
3487         }
3488       else
3489         {
3490           for(std::size_t i=0;i<nbelems;i++)
3491             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3492         }
3493     }
3494   else//meshdimension==1
3495     {
3496       double tmp[2];
3497       for(const mcIdType *i=begin;i!=end;i++)
3498         {
3499           mcIdType offset=connI[*i];
3500           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3501           double n=INTERP_KERNEL::norm<2>(tmp);
3502           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3503           *vals++=-tmp[1];
3504           *vals++=tmp[0];
3505         }
3506     }
3507   ret->setArray(array);
3508   ret->setMesh(this);
3509   ret->synchronizeTimeWithSupport();
3510   return ret.retn();
3511 }
3512
3513 /*!
3514  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3515  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3516  * and are \b not normalized.
3517  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3518  *          cells and one time. The caller is to delete this field using decrRef() as
3519  *          it is no more needed.
3520  *  \throw If the nodal connectivity of cells is not defined.
3521  *  \throw If the coordinates array is not set.
3522  *  \throw If \a this->getMeshDimension() != 1.
3523  *  \throw If \a this mesh includes cells of type other than SEG2.
3524  */
3525 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3526 {
3527   if(getMeshDimension()!=1)
3528     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3529   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3530     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3531   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3532   MCAuto<DataArrayDouble> array=DataArrayDouble::New();
3533   mcIdType nbOfCells=getNumberOfCells();
3534   int spaceDim=getSpaceDimension();
3535   array->alloc(nbOfCells,spaceDim);
3536   double *pt=array->getPointer();
3537   const double *coo=getCoords()->getConstPointer();
3538   std::vector<mcIdType> conn;
3539   conn.reserve(2);
3540   for(mcIdType i=0;i<nbOfCells;i++)
3541     {
3542       conn.resize(0);
3543       getNodeIdsOfCell(i,conn);
3544       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3545     }
3546   ret->setArray(array);
3547   ret->setMesh(this);
3548   ret->synchronizeTimeWithSupport();
3549   return ret.retn();
3550 }
3551
3552 /*!
3553  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3554  * returns a new DataArrayIdType, of length equal to the number of 2D cells in the result
3555  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3556  * from. If a result face is shared by two 3D cells, then the face in included twice in
3557  * the result mesh.
3558  *  \param [in] origin - 3 components of a point defining location of the plane.
3559  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3560  *         must be greater than 1e-6.
3561  *  \param [in] eps - half-thickness of the plane.
3562  *  \param [out] cellIds - a new instance of DataArrayIdType holding ids of 3D cells
3563  *         producing correspondent 2D cells. The caller is to delete this array
3564  *         using decrRef() as it is no more needed.
3565  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3566  *         not share the node coordinates array with \a this mesh. The caller is to
3567  *         delete this mesh using decrRef() as it is no more needed.
3568  *  \throw If the coordinates array is not set.
3569  *  \throw If the nodal connectivity of cells is not defined.
3570  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3571  *  \throw If magnitude of \a vec is less than 1e-6.
3572  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3573  *  \throw If \a this includes quadratic cells.
3574  */
3575 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayIdType *&cellIds) const
3576 {
3577   checkFullyDefined();
3578   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3579     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3580   MCAuto<DataArrayIdType> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3581   if(candidates->empty())
3582     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3583   std::vector<mcIdType> nodes;
3584   DataArrayIdType *cellIds1D=0;
3585   MCAuto<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3586   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3587   MCAuto<DataArrayIdType> desc1=DataArrayIdType::New(),desc2=DataArrayIdType::New();
3588   MCAuto<DataArrayIdType> descIndx1=DataArrayIdType::New(),descIndx2=DataArrayIdType::New();
3589   MCAuto<DataArrayIdType> revDesc1=DataArrayIdType::New(),revDesc2=DataArrayIdType::New();
3590   MCAuto<DataArrayIdType> revDescIndx1=DataArrayIdType::New(),revDescIndx2=DataArrayIdType::New();
3591   MCAuto<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3592   revDesc2=0; revDescIndx2=0;
3593   MCAuto<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3594   revDesc1=0; revDescIndx1=0;
3595   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3596   MCAuto<DataArrayIdType> cellIds1DTmp(cellIds1D);
3597   //
3598   std::vector<mcIdType> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3599   for(const mcIdType *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3600     cut3DCurve[*it]=-1;
3601   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3602   std::vector< std::pair<mcIdType,mcIdType> > cut3DSurf(mDesc2->getNumberOfCells());
3603   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3604                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3605                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3606   MCAuto<DataArrayIdType> conn(DataArrayIdType::New()),connI(DataArrayIdType::New()),cellIds2(DataArrayIdType::New());
3607   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3608   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3609   if(cellIds2->empty())
3610     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3611   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3612   ret->setCoords(mDesc1->getCoords());
3613   ret->setConnectivity(conn,connI,true);
3614   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3615   return ret.retn();
3616 }
3617
3618 /*!
3619  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3620 addition to the mesh, returns a new DataArrayIdType, 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
3621 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3622 the result mesh.
3623  *  \param [in] origin - 3 components of a point defining location of the plane.
3624  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3625  *         must be greater than 1e-6.
3626  *  \param [in] eps - half-thickness of the plane.
3627  *  \param [out] cellIds - a new instance of DataArrayIdType holding ids of faces
3628  *         producing correspondent segments. The caller is to delete this array
3629  *         using decrRef() as it is no more needed.
3630  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3631  *         mesh in 3D space. This mesh does not share the node coordinates array with
3632  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3633  *         no more needed.
3634  *  \throw If the coordinates array is not set.
3635  *  \throw If the nodal connectivity of cells is not defined.
3636  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3637  *  \throw If magnitude of \a vec is less than 1e-6.
3638  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3639  *  \throw If \a this includes quadratic cells.
3640  */
3641 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayIdType *&cellIds) const
3642 {
3643   checkFullyDefined();
3644   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3645     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3646   MCAuto<DataArrayIdType> candidates(getCellIdsCrossingPlane(origin,vec,eps));
3647   if(candidates->empty())
3648     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3649   std::vector<mcIdType> nodes;
3650   DataArrayIdType *cellIds1D(0);
3651   MCAuto<MEDCouplingUMesh> subMesh(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3652   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3653   MCAuto<DataArrayIdType> desc1(DataArrayIdType::New()),descIndx1(DataArrayIdType::New()),revDesc1(DataArrayIdType::New()),revDescIndx1(DataArrayIdType::New());
3654   MCAuto<MEDCouplingUMesh> mDesc1(subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3655   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3656   MCAuto<DataArrayIdType> cellIds1DTmp(cellIds1D);
3657   //
3658   std::vector<mcIdType> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3659   for(const mcIdType *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3660     cut3DCurve[*it]=-1;
3661   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3662   mcIdType ncellsSub=subMesh->getNumberOfCells();
3663   std::vector< std::pair<mcIdType,mcIdType> > cut3DSurf(ncellsSub);
3664   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3665                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3666                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3667   MCAuto<DataArrayIdType> conn(DataArrayIdType::New()),connI(DataArrayIdType::New()),cellIds2(DataArrayIdType::New()); connI->pushBackSilent(0);
3668   conn->alloc(0,1);
3669   const mcIdType *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3670   const mcIdType *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3671   for(mcIdType i=0;i<ncellsSub;i++)
3672     {
3673       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3674         {
3675           if(cut3DSurf[i].first!=-2)
3676             {
3677               conn->pushBackSilent(ToIdType(INTERP_KERNEL::NORM_SEG2)); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3678               connI->pushBackSilent(conn->getNumberOfTuples());
3679               cellIds2->pushBackSilent(i);
3680             }
3681           else
3682             {
3683               mcIdType cellId3DSurf=cut3DSurf[i].second;
3684               mcIdType offset=nodalI[cellId3DSurf]+1;
3685               mcIdType nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3686               for(mcIdType j=0;j<nbOfEdges;j++)
3687                 {
3688                   conn->pushBackSilent(ToIdType(INTERP_KERNEL::NORM_SEG2)); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3689                   connI->pushBackSilent(conn->getNumberOfTuples());
3690                   cellIds2->pushBackSilent(cellId3DSurf);
3691                 }
3692             }
3693         }
3694     }
3695   if(cellIds2->empty())
3696     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3697   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3698   ret->setCoords(mDesc1->getCoords());
3699   ret->setConnectivity(conn,connI,true);
3700   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3701   return ret.retn();
3702 }
3703
3704 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::clipSingle3DCellByPlane(const double origin[3], const double vec[3], double eps) const
3705 {
3706   checkFullyDefined();
3707   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3708     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3709   if(getNumberOfCells()!=1)
3710     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane works only on mesh containing exactly one cell !");
3711   //
3712   std::vector<mcIdType> nodes;
3713   findNodesOnPlane(origin,vec,eps,nodes);
3714   MCAuto<DataArrayIdType> desc1(DataArrayIdType::New()),desc2(DataArrayIdType::New()),descIndx1(DataArrayIdType::New()),descIndx2(DataArrayIdType::New()),revDesc1(DataArrayIdType::New()),revDesc2(DataArrayIdType::New()),revDescIndx1(DataArrayIdType::New()),revDescIndx2(DataArrayIdType::New());
3715   MCAuto<MEDCouplingUMesh> mDesc2(buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2));//meshDim==2 spaceDim==3
3716   revDesc2=0; revDescIndx2=0;
3717   MCAuto<MEDCouplingUMesh> mDesc1(mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));//meshDim==1 spaceDim==3
3718   revDesc1=0; revDescIndx1=0;
3719   DataArrayIdType *cellIds1D(0);
3720   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3721   MCAuto<DataArrayIdType> cellIds1DTmp(cellIds1D);
3722   std::vector<mcIdType> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3723   for(const mcIdType *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3724     cut3DCurve[*it]=-1;
3725   bool sameNbNodes;
3726   {
3727     mcIdType oldNbNodes(mDesc1->getNumberOfNodes());
3728     mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3729     sameNbNodes=(mDesc1->getNumberOfNodes()==oldNbNodes);
3730   }
3731   std::vector< std::pair<mcIdType,mcIdType> > cut3DSurf(mDesc2->getNumberOfCells());
3732   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->begin(),mDesc2->getNodalConnectivityIndex()->begin(),
3733                               mDesc1->getNodalConnectivity()->begin(),mDesc1->getNodalConnectivityIndex()->begin(),
3734                               desc1->begin(),descIndx1->begin(),cut3DSurf);
3735   MCAuto<DataArrayIdType> conn(DataArrayIdType::New()),connI(DataArrayIdType::New());
3736   connI->pushBackSilent(0); conn->alloc(0,1);
3737   {
3738     MCAuto<DataArrayIdType> cellIds2(DataArrayIdType::New()); cellIds2->alloc(0,1);
3739     assemblyForSplitFrom3DSurf(cut3DSurf,desc2->begin(),descIndx2->begin(),conn,connI,cellIds2);
3740     if(cellIds2->empty())
3741       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3742   }
3743   std::vector<std::vector<mcIdType> > res;
3744   buildSubCellsFromCut(cut3DSurf,desc2->begin(),descIndx2->begin(),mDesc1->getCoords()->begin(),eps,res);
3745   std::size_t sz(res.size());
3746   if(ToIdType(res.size())==mDesc1->getNumberOfCells() && sameNbNodes)
3747     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::clipSingle3DCellByPlane : cell is not clipped !");
3748   for(std::size_t i=0;i<sz;i++)
3749     {
3750       conn->pushBackSilent(ToIdType(INTERP_KERNEL::NORM_POLYGON));
3751       conn->insertAtTheEnd(res[i].begin(),res[i].end());
3752       connI->pushBackSilent(conn->getNumberOfTuples());
3753     }
3754   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
3755   ret->setCoords(mDesc1->getCoords());
3756   ret->setConnectivity(conn,connI,true);
3757   mcIdType nbCellsRet(ret->getNumberOfCells());
3758   //
3759   MCAuto<DataArrayDouble> vec2(DataArrayDouble::New()); vec2->alloc(1,3); std::copy(vec,vec+3,vec2->getPointer());
3760   MCAuto<MEDCouplingFieldDouble> ortho(ret->buildOrthogonalField());
3761   MCAuto<DataArrayDouble> ortho2(ortho->getArray()->selectByTupleIdSafeSlice(0,1,1));
3762   MCAuto<DataArrayDouble> dott(DataArrayDouble::Dot(ortho2,vec2));
3763   MCAuto<DataArrayDouble> ccm(ret->computeCellCenterOfMass());
3764   MCAuto<DataArrayDouble> occm;
3765   {
3766     MCAuto<DataArrayDouble> pt(DataArrayDouble::New()); pt->alloc(1,3); std::copy(origin,origin+3,pt->getPointer());
3767     occm=DataArrayDouble::Substract(ccm,pt);
3768   }
3769   vec2=DataArrayDouble::New(); vec2->alloc(nbCellsRet,3);
3770   vec2->setPartOfValuesSimple1(vec[0],0,nbCellsRet,1,0,1,1); vec2->setPartOfValuesSimple1(vec[1],0,nbCellsRet,1,1,2,1); vec2->setPartOfValuesSimple1(vec[2],0,nbCellsRet,1,2,3,1);
3771   MCAuto<DataArrayDouble> dott2(DataArrayDouble::Dot(occm,vec2));
3772   //
3773   const mcIdType *cPtr(ret->getNodalConnectivity()->begin()),*ciPtr(ret->getNodalConnectivityIndex()->begin());
3774   MCAuto<MEDCouplingUMesh> ret2(MEDCouplingUMesh::New("Clip3D",3));
3775   ret2->setCoords(mDesc1->getCoords());
3776   MCAuto<DataArrayIdType> conn2(DataArrayIdType::New()),conn2I(DataArrayIdType::New());
3777   conn2I->pushBackSilent(0); conn2->alloc(0,1);
3778   std::vector<mcIdType> cell0(1,ToIdType(INTERP_KERNEL::NORM_POLYHED));
3779   std::vector<mcIdType> cell1(1,ToIdType(INTERP_KERNEL::NORM_POLYHED));
3780   if(dott->getIJ(0,0)>0)
3781     {
3782       cell0.insert(cell0.end(),cPtr+1,cPtr+ciPtr[1]);
3783       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell1,cell1.end()));
3784     }
3785   else
3786     {
3787       cell1.insert(cell1.end(),cPtr+1,cPtr+ciPtr[1]);
3788       std::reverse_copy(cPtr+1,cPtr+ciPtr[1],std::inserter(cell0,cell0.end()));
3789     }
3790   for(mcIdType i=1;i<nbCellsRet;i++)
3791     {
3792       if(dott2->getIJ(i,0)<0)
3793         {
3794           if(ciPtr[i+1]-ciPtr[i]>=4)
3795             {
3796               cell0.push_back(-1);
3797               cell0.insert(cell0.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
3798             }
3799         }
3800       else
3801         {
3802           if(ciPtr[i+1]-ciPtr[i]>=4)
3803             {
3804               cell1.push_back(-1);
3805               cell1.insert(cell1.end(),cPtr+ciPtr[i]+1,cPtr+ciPtr[i+1]);
3806             }
3807         }
3808     }
3809   conn2->insertAtTheEnd(cell0.begin(),cell0.end());
3810   conn2I->pushBackSilent(conn2->getNumberOfTuples());
3811   conn2->insertAtTheEnd(cell1.begin(),cell1.end());
3812   conn2I->pushBackSilent(conn2->getNumberOfTuples());
3813   ret2->setConnectivity(conn2,conn2I,true);
3814   ret2->checkConsistencyLight();
3815   ret2->orientCorrectlyPolyhedrons();
3816   return ret2;
3817 }
3818
3819 /*!
3820  * Finds cells whose bounding boxes intersect a given plane.
3821  *  \param [in] origin - 3 components of a point defining location of the plane.
3822  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3823  *         must be greater than 1e-6.
3824  *  \param [in] eps - half-thickness of the plane.
3825  *  \return DataArrayIdType * - a new instance of DataArrayIdType holding ids of the found
3826  *         cells. The caller is to delete this array using decrRef() as it is no more
3827  *         needed.
3828  *  \throw If the coordinates array is not set.
3829  *  \throw If the nodal connectivity of cells is not defined.
3830  *  \throw If \a this->getSpaceDimension() != 3.
3831  *  \throw If magnitude of \a vec is less than 1e-6.
3832  *  \sa buildSlice3D()
3833  */
3834 DataArrayIdType *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3835 {
3836   checkFullyDefined();
3837   if(getSpaceDimension()!=3)
3838     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3839   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3840   if(normm<1e-6)
3841     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3842   double vec2[3];
3843   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3844   double angle=acos(vec[2]/normm);
3845   MCAuto<DataArrayIdType> cellIds;
3846   double bbox[6];
3847   if(angle>eps)
3848     {
3849       MCAuto<DataArrayDouble> coo=_coords->deepCopy();
3850       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3851       if(normm2/normm>1e-6)
3852         DataArrayDouble::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer(),coo->getPointer());
3853       MCAuto<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3854       mw->setCoords(coo);
3855       mw->getBoundingBox(bbox);
3856       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3857       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3858     }
3859   else
3860     {
3861       getBoundingBox(bbox);
3862       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3863       cellIds=getCellsInBoundingBox(bbox,eps);
3864     }
3865   return cellIds.retn();
3866 }
3867
3868 /*!
3869  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3870  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3871  * No consideration of coordinate is done by this method.
3872  * 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)
3873  * If not false is returned. In case that false is returned a call to MEDCoupling::MEDCouplingUMesh::mergeNodes could be useful.
3874  */
3875 bool MEDCouplingUMesh::isContiguous1D() const
3876 {
3877   if(getMeshDimension()!=1)
3878     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3879   mcIdType nbCells=getNumberOfCells();
3880   if(nbCells<1)
3881     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3882   const mcIdType *connI(_nodal_connec_index->begin()),*conn(_nodal_connec->begin());
3883   mcIdType ref=conn[connI[0]+2];
3884   for(mcIdType i=1;i<nbCells;i++)
3885     {
3886       if(conn[connI[i]+1]!=ref)
3887         return false;
3888       ref=conn[connI[i]+2];
3889     }
3890   return true;
3891 }
3892
3893 /*!
3894  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3895  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3896  * \param pt reference point of the line
3897  * \param v normalized director vector of the line
3898  * \param eps max precision before throwing an exception
3899  * \param res output of size this->getNumberOfCells
3900  */
3901 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3902 {
3903   if(getMeshDimension()!=1)
3904     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3905   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3906     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3907   if(getSpaceDimension()!=3)
3908     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3909   MCAuto<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3910   const double *fPtr=f->getArray()->getConstPointer();
3911   double tmp[3];
3912   for(mcIdType i=0;i<getNumberOfCells();i++)
3913     {
3914       const double *tmp1=fPtr+3*i;
3915       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3916       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3917       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3918       double n1=INTERP_KERNEL::norm<3>(tmp);
3919       n1/=INTERP_KERNEL::norm<3>(tmp1);
3920       if(n1>eps)
3921         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3922     }
3923   const double *coo=getCoords()->getConstPointer();
3924   for(mcIdType i=0;i<getNumberOfNodes();i++)
3925     {
3926       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3927       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3928       res[i]=std::accumulate(tmp,tmp+3,0.);
3929     }
3930 }
3931
3932 /*!
3933  * 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.
3934  * \a this is expected to be a mesh so that its space dimension is equal to its
3935  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3936  * 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).
3937  *
3938  * 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
3939  * 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).
3940  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3941  *
3942  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3943  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3944  *
3945  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3946  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3947  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3948  * \return the positive value of the distance.
3949  * \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
3950  * dimension - 1.
3951  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3952  */
3953 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, mcIdType& cellId) const
3954 {
3955   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3956   if(meshDim!=spaceDim-1)
3957     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3958   if(meshDim!=2 && meshDim!=1)
3959     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3960   checkFullyDefined();
3961   if(ToIdType(std::distance(ptBg,ptEnd))!=spaceDim)
3962     { 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()); }
3963   DataArrayIdType *ret1=0;
3964   MCAuto<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,DeallocType::C_DEALLOC,1,spaceDim);
3965   MCAuto<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3966   MCAuto<DataArrayIdType> ret1Safe(ret1);
3967   cellId=*ret1Safe->begin();
3968   return *ret0->begin();
3969 }
3970
3971 /*!
3972  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3973  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance.
3974  * 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
3975  * 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).
3976  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3977  *
3978  * \a this is expected to be a mesh so that its space dimension is equal to its
3979  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3980  * 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).
3981  *
3982  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3983  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3984  *
3985  * \param [in] pts the list of points in which each tuple represents a point
3986  * \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.
3987  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3988  * \throw if number of components of \a pts is not equal to the space dimension.
3989  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3990  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3991  */
3992 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayIdType *& cellIds) const
3993 {
3994   if(!pts)
3995     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3996   pts->checkAllocated();
3997   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3998   if(meshDim!=spaceDim-1)
3999     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4000   if(meshDim!=2 && meshDim!=1)
4001     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4002   if(ToIdType(pts->getNumberOfComponents())!=spaceDim)
4003     {
4004       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4005       throw INTERP_KERNEL::Exception(oss.str());
4006     }
4007   checkFullyDefined();
4008   mcIdType nbCells=getNumberOfCells();
4009   if(nbCells==0)
4010     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4011   mcIdType nbOfPts=pts->getNumberOfTuples();
4012   MCAuto<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4013   MCAuto<DataArrayIdType> ret1=DataArrayIdType::New(); ret1->alloc(nbOfPts,1);
4014   const mcIdType *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4015   double *ret0Ptr=ret0->getPointer(); mcIdType *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4016   MCAuto<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4017   const double *bbox(bboxArr->begin());
4018   switch(spaceDim)
4019   {
4020     case 3:
4021       {
4022         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4023         for(mcIdType i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4024           {
4025             double x=std::numeric_limits<double>::max();
4026             std::vector<mcIdType> elems;
4027             myTree.getMinDistanceOfMax(ptsPtr,x);
4028             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4029             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4030           }
4031         break;
4032       }
4033     case 2:
4034       {
4035         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4036         for(mcIdType i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4037           {
4038             double x=std::numeric_limits<double>::max();
4039             std::vector<mcIdType> elems;
4040             myTree.getMinDistanceOfMax(ptsPtr,x);
4041             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4042             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4043           }
4044         break;
4045       }
4046     default:
4047       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4048   }
4049   cellIds=ret1.retn();
4050   return ret0.retn();
4051 }
4052
4053 /// @cond INTERNAL
4054
4055 /// @endcond
4056
4057 /*!
4058  * Finds cells in contact with a ball (i.e. a point with precision).
4059  * 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.
4060  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4061  *
4062  * \warning This method is suitable if the caller intends to evaluate only one
4063  *          point, for more points getCellsContainingPoints() is recommended as it is
4064  *          faster.
4065  *  \param [in] pos - array of coordinates of the ball central point.
4066  *  \param [in] eps - ball radius.
4067  *  \return mcIdType - a smallest id of cells being in contact with the ball, -1 in case
4068  *         if there are no such cells.
4069  *  \throw If the coordinates array is not set.
4070  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4071  */
4072 mcIdType MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4073 {
4074   std::vector<mcIdType> elts;
4075   getCellsContainingPoint(pos,eps,elts);
4076   if(elts.empty())
4077     return -1;
4078   return elts.front();
4079 }
4080
4081 /*!
4082  * Finds cells in contact with a ball (i.e. a point with precision).
4083  * 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.
4084  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4085  * \warning This method is suitable if the caller intends to evaluate only one
4086  *          point, for more points getCellsContainingPoints() is recommended as it is
4087  *          faster.
4088  *  \param [in] pos - array of coordinates of the ball central point.
4089  *  \param [in] eps - ball radius.
4090  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4091  *         before inserting ids.
4092  *  \throw If the coordinates array is not set.
4093  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4094  *
4095  *  \if ENABLE_EXAMPLES
4096  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4097  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4098  *  \endif
4099  */
4100 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<mcIdType>& elts) const
4101 {
4102   MCAuto<DataArrayIdType> eltsUg,eltsIndexUg;
4103   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4104   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4105 }
4106
4107 void MEDCouplingUMesh::getCellsContainingPointsZeAlg(const double *pos, mcIdType nbOfPoints, double eps,
4108                                                      MCAuto<DataArrayIdType>& elts, MCAuto<DataArrayIdType>& eltsIndex,
4109                                                      std::function<bool(INTERP_KERNEL::NormalizedCellType,mcIdType)> sensibilityTo2DQuadraticLinearCellsFunc) const
4110 {
4111   int spaceDim(getSpaceDimension()),mDim(getMeshDimension());
4112   if(spaceDim==3)
4113     {
4114       if(mDim==3)
4115         {
4116           const double *coords=_coords->getConstPointer();
4117           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex,sensibilityTo2DQuadraticLinearCellsFunc);
4118         }
4119       else
4120         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4121     }
4122   else if(spaceDim==2)
4123     {
4124       if(mDim==2)
4125         {
4126           const double *coords=_coords->getConstPointer();
4127           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex,sensibilityTo2DQuadraticLinearCellsFunc);
4128         }
4129       else
4130         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4131     }
4132   else if(spaceDim==1)
4133     {
4134       if(mDim==1)
4135         {
4136           const double *coords=_coords->getConstPointer();
4137           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex,sensibilityTo2DQuadraticLinearCellsFunc);
4138         }
4139       else
4140         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4141     }
4142   else
4143     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4144 }
4145
4146 /*!
4147  * Finds cells in contact with several balls (i.e. points with precision).
4148  * This method is an extension of getCellContainingPoint() and
4149  * getCellsContainingPoint() for the case of multiple points.
4150  * 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.
4151  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4152  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4153  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4154  *         this->getSpaceDimension() * \a nbOfPoints
4155  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4156  *  \param [in] eps - radius of balls (i.e. the precision).
4157  *  \param [out] elts - vector returning ids of found cells.
4158  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4159  *         dividing cell ids in \a elts into groups each referring to one
4160  *         point. Its every element (except the last one) is an index pointing to the
4161  *         first id of a group of cells. For example cells in contact with the *i*-th
4162  *         point are described by following range of indices:
4163  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4164  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4165  *         Number of cells in contact with the *i*-th point is
4166  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4167  *  \throw If the coordinates array is not set.
4168  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4169  *
4170  *  \if ENABLE_EXAMPLES
4171  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4172  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4173  *  \endif
4174  */
4175 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, mcIdType nbOfPoints, double eps,
4176                                                 MCAuto<DataArrayIdType>& elts, MCAuto<DataArrayIdType>& eltsIndex) const
4177 {
4178   auto yesImSensibleTo2DQuadraticLinearCellsFunc([](INTERP_KERNEL::NormalizedCellType ct, int mdim) { return INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic() && mdim == 2; } );
4179   this->getCellsContainingPointsZeAlg(pos,nbOfPoints,eps,elts,eltsIndex,yesImSensibleTo2DQuadraticLinearCellsFunc);
4180 }
4181
4182 /*!
4183  * Behaves like MEDCouplingMesh::getCellsContainingPoints for cells in \a this that are linear.
4184  * For quadratic cells in \a this, this method behaves by just considering linear part of cells.
4185  * This method is here only for backward compatibility (interpolation GaussPoints to GaussPoints).
4186  * 
4187  * \sa MEDCouplingUMesh::getCellsContainingPoints, MEDCouplingRemapper::prepareNotInterpKernelOnlyGaussGauss
4188  */
4189 void MEDCouplingUMesh::getCellsContainingPointsLinearPartOnlyOnNonDynType(const double *pos, mcIdType nbOfPoints, double eps, MCAuto<DataArrayIdType>& elts, MCAuto<DataArrayIdType>& eltsIndex) const
4190 {
4191   auto noImNotSensibleTo2DQuadraticLinearCellsFunc([](INTERP_KERNEL::NormalizedCellType,mcIdType) { return false; } );
4192   this->getCellsContainingPointsZeAlg(pos,nbOfPoints,eps,elts,eltsIndex,noImNotSensibleTo2DQuadraticLinearCellsFunc);
4193 }
4194
4195 /*!
4196  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4197  * least two its edges intersect each other anywhere except their extremities. An
4198  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4199  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4200  *         cleared before filling in.
4201  *  \param [in] eps - precision.
4202  *  \throw If \a this->getMeshDimension() != 2.
4203  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4204  */
4205 void MEDCouplingUMesh::checkButterflyCells(std::vector<mcIdType>& cells, double eps) const
4206 {
4207   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4208   if(getMeshDimension()!=2)
4209     throw INTERP_KERNEL::Exception(msg);
4210   int spaceDim=getSpaceDimension();
4211   if(spaceDim!=2 && spaceDim!=3)
4212     throw INTERP_KERNEL::Exception(msg);
4213   const mcIdType *conn=_nodal_connec->getConstPointer();
4214   const mcIdType *connI=_nodal_connec_index->getConstPointer();
4215   mcIdType nbOfCells=getNumberOfCells();
4216   std::vector<double> cell2DinS2;
4217   for(mcIdType i=0;i<nbOfCells;i++)
4218     {
4219       mcIdType offset=connI[i];
4220       mcIdType nbOfNodesForCell=connI[i+1]-offset-1;
4221       if(nbOfNodesForCell<=3)
4222         continue;
4223       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4224       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4225       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4226         cells.push_back(i);
4227       cell2DinS2.clear();
4228     }
4229 }
4230
4231 /*!
4232  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4233  *
4234  * 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.
4235  * 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.
4236  *
4237  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4238  * This convex envelop is computed using Jarvis march algorithm.
4239  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4240  * 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)
4241  * 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.
4242  *
4243  * \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.
4244  * \sa MEDCouplingUMesh::colinearize2D
4245  */
4246 DataArrayIdType *MEDCouplingUMesh::convexEnvelop2D()
4247 {
4248   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4249     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4250   checkFullyDefined();
4251   const double *coords=getCoords()->getConstPointer();
4252   mcIdType nbOfCells=getNumberOfCells();
4253   MCAuto<DataArrayIdType> nodalConnecIndexOut=DataArrayIdType::New();
4254   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4255   MCAuto<DataArrayIdType> nodalConnecOut(DataArrayIdType::New());
4256   mcIdType *workIndexOut=nodalConnecIndexOut->getPointer();
4257   *workIndexOut=0;
4258   const mcIdType *nodalConnecIn=_nodal_connec->getConstPointer();
4259   const mcIdType *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4260   std::set<INTERP_KERNEL::NormalizedCellType> types;
4261   MCAuto<DataArrayIdType> isChanged(DataArrayIdType::New());
4262   isChanged->alloc(0,1);
4263   for(mcIdType i=0;i<nbOfCells;i++,workIndexOut++)
4264     {
4265       mcIdType pos=nodalConnecOut->getNumberOfTuples();
4266       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4267         isChanged->pushBackSilent(i);
4268       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4269       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4270     }
4271   if(isChanged->empty())
4272     return 0;
4273   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4274   _types=types;
4275   return isChanged.retn();
4276 }
4277
4278 /*!
4279  * This method is \b NOT const because it can modify \a this.
4280  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4281  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4282  * \param policy specifies the type of extrusion chosen:
4283  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4284  *   will be repeated to build each level
4285  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4286  *   the 3 preceding points of the 1D mesh. The center of the arc is the center of rotation for each level, the rotation is done
4287  *   along an axis normal to the plane containing the arc, and finally the angle of rotation is defined by the first two points on the
4288  *   arc.
4289  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4290  */
4291 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4292 {
4293   checkFullyDefined();
4294   mesh1D->checkFullyDefined();
4295   if(!mesh1D->isContiguous1D())
4296     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4297   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4298     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4299   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4300     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4301   if(mesh1D->getMeshDimension()!=1)
4302     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4303   bool isQuad=false;
4304   if(isPresenceOfQuadratic())
4305     {
4306       if(mesh1D->isFullyQuadratic())
4307         isQuad=true;
4308       else
4309         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4310     }
4311   mcIdType oldNbOfNodes(getNumberOfNodes());
4312   MCAuto<DataArrayDouble> newCoords;
4313   switch(policy)
4314   {
4315     case 0:
4316       {
4317         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4318         break;
4319       }
4320     case 1:
4321       {
4322         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4323         break;
4324       }
4325     default:
4326       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4327   }
4328   setCoords(newCoords);
4329   MCAuto<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4330   updateTime();
4331   return ret.retn();
4332 }
4333
4334
4335 /*!
4336  * Checks if \a this mesh is constituted by only quadratic cells.
4337  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4338  *  \throw If the coordinates array is not set.
4339  *  \throw If the nodal connectivity of cells is not defined.
4340  */
4341 bool MEDCouplingUMesh::isFullyQuadratic() const
4342 {
4343   checkFullyDefined();
4344   bool ret=true;
4345   mcIdType nbOfCells=getNumberOfCells();
4346   for(mcIdType i=0;i<nbOfCells && ret;i++)
4347     {
4348       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4349       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4350       ret=cm.isQuadratic();
4351     }
4352   return ret;
4353 }
4354
4355 /*!
4356  * Checks if \a this mesh includes any quadratic cell.
4357  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4358  *  \throw If the coordinates array is not set.
4359  *  \throw If the nodal connectivity of cells is not defined.
4360  */
4361 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4362 {
4363   checkFullyDefined();
4364   bool ret=false;
4365   mcIdType nbOfCells=getNumberOfCells();
4366   for(mcIdType i=0;i<nbOfCells && !ret;i++)
4367     {
4368       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4369       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4370       ret=cm.isQuadratic();
4371     }
4372   return ret;
4373 }
4374
4375 /*!
4376  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4377  * this mesh, it remains unchanged.
4378  *  \throw If the coordinates array is not set.
4379  *  \throw If the nodal connectivity of cells is not defined.
4380  */
4381 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4382 {
4383   checkFullyDefined();
4384   mcIdType nbOfCells=getNumberOfCells();
4385   mcIdType delta=0;
4386   const mcIdType *iciptr=_nodal_connec_index->begin();
4387   for(mcIdType i=0;i<nbOfCells;i++)
4388     {
4389       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4390       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4391       if(cm.isQuadratic())
4392         {
4393           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4394           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4395           if(!cml.isDynamic())
4396             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4397           else
4398             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4399         }
4400     }
4401   if(delta==0)
4402     return ;
4403   MCAuto<DataArrayIdType> newConn(DataArrayIdType::New()),newConnI(DataArrayIdType::New());
4404   const mcIdType *icptr(_nodal_connec->begin());
4405   newConn->alloc(getNodalConnectivityArrayLen()-delta,1);
4406   newConnI->alloc(nbOfCells+1,1);
4407   mcIdType *ocptr(newConn->getPointer()),*ociptr(newConnI->getPointer());
4408   *ociptr=0;
4409   _types.clear();
4410   for(mcIdType i=0;i<nbOfCells;i++,ociptr++)
4411     {
4412       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4413       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4414       if(!cm.isQuadratic())
4415         {
4416           _types.insert(type);
4417           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4418           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4419         }
4420       else
4421         {
4422           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4423           _types.insert(typel);
4424           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4425           mcIdType newNbOfNodes=cml.getNumberOfNodes();
4426           if(cml.isDynamic())
4427             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4428           *ocptr++=ToIdType(typel);
4429           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4430           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4431         }
4432     }
4433   setConnectivity(newConn,newConnI,false);
4434 }
4435
4436 /*!
4437  * This method converts all linear cell in \a this to quadratic one.
4438  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4439  * 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)
4440  * 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.
4441  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4442  * end of the existing coordinates.
4443  *
4444  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4445  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4446  * \return a newly created DataArrayIdType instance that the caller should deal with containing cell ids of converted cells.
4447  *
4448  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4449  *
4450  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4451  */
4452 DataArrayIdType *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4453 {
4454   DataArrayIdType *conn=0,*connI=0;
4455   DataArrayDouble *coords=0;
4456   std::set<INTERP_KERNEL::NormalizedCellType> types;
4457   checkFullyDefined();
4458   MCAuto<DataArrayIdType> ret,connSafe,connISafe;
4459   MCAuto<DataArrayDouble> coordsSafe;
4460   int meshDim=getMeshDimension();
4461   switch(conversionType)
4462   {
4463     case 0:
4464       switch(meshDim)
4465       {
4466         case 1:
4467           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4468           connSafe=conn; connISafe=connI; coordsSafe=coords;
4469           break;
4470         case 2:
4471           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4472           connSafe=conn; connISafe=connI; coordsSafe=coords;
4473           break;
4474         case 3:
4475           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4476           connSafe=conn; connISafe=connI; coordsSafe=coords;
4477           break;
4478         default:
4479           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4480       }
4481       break;
4482         case 1:
4483           {
4484             switch(meshDim)
4485             {
4486               case 1:
4487                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4488                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4489                 break;
4490               case 2:
4491                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4492                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4493                 break;
4494               case 3:
4495                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4496                 connSafe=conn; connISafe=connI; coordsSafe=coords;
4497                 break;
4498               default:
4499                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4500             }
4501             break;
4502           }
4503         default:
4504           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4505   }
4506   setConnectivity(connSafe,connISafe,false);
4507   _types=types;
4508   setCoords(coordsSafe);
4509   return ret.retn();
4510 }
4511
4512 /*!
4513  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
4514  * so that the number of cells remains the same. Quadratic faces are converted to
4515  * polygons. This method works only for 2D meshes in
4516  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
4517  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
4518  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
4519  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
4520  *         a polylinized edge constituting the input polygon.
4521  *  \throw If the coordinates array is not set.
4522  *  \throw If the nodal connectivity of cells is not defined.
4523  *  \throw If \a this->getMeshDimension() != 2.
4524  *  \throw If \a this->getSpaceDimension() != 2.
4525  */
4526 void MEDCouplingUMesh::tessellate2D(double eps)
4527 {
4528   int meshDim(getMeshDimension()),spaceDim(getSpaceDimension());
4529   if(spaceDim!=2)
4530     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : works only with space dimension equal to 2 !");
4531   switch(meshDim)
4532     {
4533     case 1:
4534       return tessellate2DCurveInternal(eps);
4535     case 2:
4536       return tessellate2DInternal(eps);
4537     default:
4538       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D : mesh dimension must be in [1,2] !");
4539     }
4540 }
4541
4542 #if 0
4543 /*!
4544  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
4545  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
4546  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
4547  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
4548  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
4549  * This method can be seen as the opposite method of colinearize2D.
4550  * This method can be lead to create some new nodes if quadratic polygon cells have to be split. In this case the added nodes will be put at the end
4551  * to avoid to modify the numbering of existing nodes.
4552  *
4553  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
4554  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
4555  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
4556  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
4557  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
4558  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
4559  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
4560  *
4561  * \sa buildDescendingConnectivity2
4562  */
4563 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayIdType *nodeIdsToAdd, const DataArrayIdType *nodeIdsIndexToAdd, const DataArrayIdType *edgeIdsToBeSplit,
4564                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayIdType *desc, const DataArrayIdType *descI, const DataArrayIdType *revDesc, const DataArrayIdType *revDescI)
4565 {
4566   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
4567     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
4568   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
4569   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
4570     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
4571   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
4572     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
4573   //DataArrayIdType *out0(0),*outi0(0);
4574   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
4575   //MCAuto<DataArrayIdType> out0s(out0),outi0s(outi0);
4576   //out0s=out0s->buildUnique(); out0s->sort(true);
4577 }
4578 #endif
4579
4580
4581 /*!
4582  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
4583  * In addition, returns an array mapping new cells to old ones. <br>
4584  * This method typically increases the number of cells in \a this mesh
4585  * but the number of nodes remains \b unchanged.
4586  * That's why the 3D splitting policies
4587  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
4588  *  \param [in] policy - specifies a pattern used for splitting.
4589  * The semantic of \a policy is:
4590  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
4591  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
4592  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
4593  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
4594  *
4595  *
4596  *  \return DataArrayIdType * - a new instance of DataArrayIdType holding, for each new cell,
4597  *          an id of old cell producing it. The caller is to delete this array using
4598  *         decrRef() as it is no more needed.
4599  *
4600  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
4601  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
4602  *          and \a this->getMeshDimension() != 3.
4603  *  \throw If \a policy is not one of the four discussed above.
4604  *  \throw If the nodal connectivity of cells is not defined.
4605  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
4606  */
4607 DataArrayIdType *MEDCouplingUMesh::simplexize(int policy)
4608 {
4609   switch(policy)
4610   {
4611     case 0:
4612       return simplexizePol0();
4613     case 1:
4614       return simplexizePol1();
4615     case INTERP_KERNEL::PLANAR_FACE_5:
4616         return simplexizePlanarFace5();
4617     case INTERP_KERNEL::PLANAR_FACE_6:
4618         return simplexizePlanarFace6();
4619     default:
4620       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)");
4621   }
4622 }
4623
4624 /*!
4625  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
4626  * - 1D: INTERP_KERNEL::NORM_SEG2
4627  * - 2D: INTERP_KERNEL::NORM_TRI3
4628  * - 3D: INTERP_KERNEL::NORM_TETRA4.
4629  *
4630  * This method is useful for users that need to use P1 field services as
4631  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
4632  * All these methods need mesh support containing only simplex cells.
4633  *  \return bool - \c true if there are only simplex cells in \a this mesh.
4634  *  \throw If the coordinates array is not set.
4635  *  \throw If the nodal connectivity of cells is not defined.
4636  *  \throw If \a this->getMeshDimension() < 1.
4637  */
4638 bool MEDCouplingUMesh::areOnlySimplexCells() const
4639 {
4640   checkFullyDefined();
4641   int mdim=getMeshDimension();
4642   if(mdim<1 || mdim>3)
4643     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
4644   mcIdType nbCells=getNumberOfCells();
4645   const mcIdType *conn=_nodal_connec->begin();
4646   const mcIdType *connI=_nodal_connec_index->begin();
4647   for(mcIdType i=0;i<nbCells;i++)
4648     {
4649       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4650       if(!cm.isSimplex())
4651         return false;
4652     }
4653   return true;
4654 }
4655
4656
4657
4658 /*!
4659  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
4660  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
4661  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell.
4662  * Quadratic cells in 2D are also handled. In those cells edges where start=end=midpoint are removed.
4663  * This method does \b not perform geometrical checks and checks only nodal connectivity of cells,
4664  * so it can be useful to call mergeNodes() before calling this method.
4665  *  \throw If \a this->getMeshDimension() <= 1.
4666  *  \throw If the coordinates array is not set.
4667  *  \throw If the nodal connectivity of cells is not defined.
4668  */
4669 void MEDCouplingUMesh::convertDegeneratedCells()
4670 {
4671   checkFullyDefined();
4672   if(getMeshDimension()<=1)
4673     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
4674   mcIdType nbOfCells=getNumberOfCells();
4675   if(nbOfCells<1)
4676     return ;
4677   mcIdType initMeshLgth=getNodalConnectivityArrayLen();
4678   mcIdType *conn=_nodal_connec->getPointer();
4679   mcIdType *index=_nodal_connec_index->getPointer();
4680   mcIdType posOfCurCell=0;
4681   mcIdType newPos=0;
4682   mcIdType lgthOfCurCell;
4683   for(mcIdType i=0;i<nbOfCells;i++)
4684     {
4685       lgthOfCurCell=index[i+1]-posOfCurCell;
4686       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
4687       mcIdType newLgth;
4688       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
4689                                                                                                      conn+newPos+1,newLgth);
4690       conn[newPos]=newType;
4691       newPos+=newLgth+1;
4692       posOfCurCell=index[i+1];
4693       index[i+1]=newPos;
4694     }
4695   if(newPos!=initMeshLgth)
4696     _nodal_connec->reAlloc(newPos);
4697   computeTypes();
4698 }
4699
4700 /*!
4701  * Same as MEDCouplingUMesh::convertDegeneratedCells() plus deletion of the flat cells.
4702  * A cell is flat in the following cases:
4703  *   - for a linear cell, all points in the connectivity are equal
4704  *   - for a quadratic cell, either the above, or a quadratic polygon with two (linear) points and two
4705  *   identical quadratic points
4706  * \return a new instance of DataArrayIdType holding ids of removed cells. The caller is to delete
4707  *      this array using decrRef() as it is no more needed.
4708  */
4709 DataArrayIdType *MEDCouplingUMesh::convertDegeneratedCellsAndRemoveFlatOnes()
4710 {
4711   checkFullyDefined();
4712   if(getMeshDimension()<=1)
4713     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
4714   mcIdType nbOfCells=getNumberOfCells();
4715   MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(0,1);
4716   if(nbOfCells<1)
4717     return ret.retn();
4718   mcIdType initMeshLgth=getNodalConnectivityArrayLen();
4719   mcIdType *conn=_nodal_connec->getPointer();
4720   mcIdType *index=_nodal_connec_index->getPointer();
4721   mcIdType posOfCurCell=0;
4722   mcIdType newPos=0;
4723   mcIdType lgthOfCurCell, nbDelCells(0);
4724   for(mcIdType i=0;i<nbOfCells;i++)
4725     {
4726       lgthOfCurCell=index[i+1]-posOfCurCell;
4727       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
4728       mcIdType newLgth;
4729       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
4730                                                                                                      conn+newPos+1,newLgth);
4731       // Shall we delete the cell if it is completely degenerated:
4732       bool delCell=INTERP_KERNEL::CellSimplify::isFlatCell(conn, newPos, newLgth, newType);
4733       if (delCell)
4734         {
4735           nbDelCells++;
4736           ret->pushBackSilent(i);
4737         }
4738       else   //if the cell is to be deleted, simply stay at the same place
4739         {
4740           conn[newPos]=newType;
4741           newPos+=newLgth+1;
4742         }
4743       posOfCurCell=index[i+1];
4744       index[i+1-nbDelCells]=newPos;
4745     }
4746   if(newPos!=initMeshLgth)
4747     _nodal_connec->reAlloc(newPos);
4748   const mcIdType nCellDel=ret->getNumberOfTuples();
4749   if (nCellDel)
4750     _nodal_connec_index->reAlloc(nbOfCells-nCellDel+1);
4751   computeTypes();
4752   return ret.retn();
4753 }
4754
4755 /*!
4756  * This method remove null 1D cells from \a this. A 1D cell is considered null if start node is equal to end node.
4757  * Only connectivity is considered here.
4758  */
4759 bool MEDCouplingUMesh::removeDegenerated1DCells()
4760 {
4761   checkConnectivityFullyDefined();
4762   if(getMeshDimension()!=1)
4763     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::removeDegenerated1DCells works on umeshes with meshdim equals to 1 !");
4764   std::size_t nbCells(getNumberOfCells()),newSize(0),newSize2(0);
4765   const mcIdType *conn(getNodalConnectivity()->begin()),*conni(getNodalConnectivityIndex()->begin());
4766   {
4767     for(std::size_t i=0;i<nbCells;i++)
4768       {
4769         INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[conni[i]]);
4770         if(ct==INTERP_KERNEL::NORM_SEG2 || ct==INTERP_KERNEL::NORM_SEG3)
4771           {
4772             if(conn[conni[i]+1]!=conn[conni[i]+2])
4773               {
4774                 newSize++;
4775                 newSize2+=conni[i+1]-conni[i];
4776               }
4777           }
4778         else
4779           {
4780             std::ostringstream oss; oss << "MEDCouplingUMesh::removeDegenerated1DCells : cell #" << i << " in this is not of type SEG2/SEG3 !";
4781             throw INTERP_KERNEL::Exception(oss.str());
4782           }
4783       }
4784   }
4785   if(newSize==nbCells)//no cells has been removed -> do nothing
4786     return false;
4787   MCAuto<DataArrayIdType> newConn(DataArrayIdType::New()),newConnI(DataArrayIdType::New()); newConnI->alloc(newSize+1,1); newConn->alloc(newSize2,1);
4788   mcIdType *newConnPtr(newConn->getPointer()),*newConnIPtr(newConnI->getPointer()); newConnIPtr[0]=0;
4789   for(std::size_t i=0;i<nbCells;i++)
4790     {
4791       if(conn[conni[i]+1]!=conn[conni[i]+2])
4792         {
4793           newConnIPtr[1]=newConnIPtr[0]+conni[i+1]-conni[i];
4794           newConnPtr=std::copy(conn+conni[i],conn+conni[i+1],newConnPtr);
4795           newConnIPtr++;
4796         }
4797     }
4798   setConnectivity(newConn,newConnI,true);
4799   return true;
4800 }
4801
4802 /*!
4803  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
4804  * A cell is considered to be oriented correctly if an angle between its
4805  * normal vector and a given vector is less than \c PI / \c 2.
4806  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
4807  *         cells.
4808  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
4809  *         checked.
4810  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
4811  *         is not cleared before filling in.
4812  *  \throw If \a this->getMeshDimension() != 2.
4813  *  \throw If \a this->getSpaceDimension() != 3.
4814  *
4815  *  \if ENABLE_EXAMPLES
4816  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
4817  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
4818  *  \endif
4819  */
4820 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<mcIdType>& cells) const
4821 {
4822   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4823     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
4824   mcIdType nbOfCells=getNumberOfCells();
4825   const mcIdType *conn=_nodal_connec->begin();
4826   const mcIdType *connI=_nodal_connec_index->begin();
4827   const double *coordsPtr=_coords->begin();
4828   for(mcIdType i=0;i<nbOfCells;i++)
4829     {
4830       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4831       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4832         {
4833           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
4834           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4835             cells.push_back(i);
4836         }
4837     }
4838 }
4839
4840 /*!
4841  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
4842  * considered to be oriented correctly if an angle between its normal vector and a
4843  * given vector is less than \c PI / \c 2.
4844  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
4845  *         cells.
4846  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
4847  *         checked.
4848  *  \throw If \a this->getMeshDimension() != 2.
4849  *  \throw If \a this->getSpaceDimension() != 3.
4850  *
4851  *  \if ENABLE_EXAMPLES
4852  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
4853  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
4854  *  \endif
4855  *
4856  *  \sa changeOrientationOfCells
4857  */
4858 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
4859 {
4860   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
4861     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
4862   mcIdType nbOfCells=getNumberOfCells();
4863   mcIdType *conn(_nodal_connec->getPointer());
4864   const mcIdType *connI(_nodal_connec_index->begin());
4865   const double *coordsPtr(_coords->begin());
4866   bool isModified(false);
4867   for(mcIdType i=0;i<nbOfCells;i++)
4868     {
4869       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4870       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
4871         {
4872           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4873           bool isQuadratic(cm.isQuadratic());
4874           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4875             {
4876               isModified=true;
4877               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4878             }
4879         }
4880     }
4881   if(isModified)
4882     _nodal_connec->declareAsNew();
4883   updateTime();
4884 }
4885
4886 /*!
4887  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
4888  *
4889  * \sa orientCorrectly2DCells
4890  */
4891 void MEDCouplingUMesh::changeOrientationOfCells()
4892 {
4893   int mdim(getMeshDimension());
4894   if(mdim!=2 && mdim!=1)
4895     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
4896   mcIdType nbOfCells=getNumberOfCells();
4897   mcIdType *conn(_nodal_connec->getPointer());
4898   const mcIdType *connI(_nodal_connec_index->begin());
4899   if(mdim==2)
4900     {//2D
4901       for(mcIdType i=0;i<nbOfCells;i++)
4902         {
4903           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4904           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4905           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4906         }
4907     }
4908   else
4909     {//1D
4910       for(mcIdType i=0;i<nbOfCells;i++)
4911         {
4912           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4913           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
4914           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
4915         }
4916     }
4917 }
4918
4919 /*!
4920  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
4921  * oriented facets. The normal vector of the facet should point out of the cell.
4922  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
4923  *         is not cleared before filling in.
4924  *  \throw If \a this->getMeshDimension() != 3.
4925  *  \throw If \a this->getSpaceDimension() != 3.
4926  *  \throw If the coordinates array is not set.
4927  *  \throw If the nodal connectivity of cells is not defined.
4928  *
4929  *  \if ENABLE_EXAMPLES
4930  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
4931  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
4932  *  \endif
4933  */
4934 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<mcIdType>& cells) const
4935 {
4936   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4937     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
4938   mcIdType nbOfCells=getNumberOfCells();
4939   const mcIdType *conn=_nodal_connec->begin();
4940   const mcIdType *connI=_nodal_connec_index->begin();
4941   const double *coordsPtr=_coords->begin();
4942   for(mcIdType i=0;i<nbOfCells;i++)
4943     {
4944       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4945       if(type==INTERP_KERNEL::NORM_POLYHED)
4946         {
4947           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4948             cells.push_back(i);
4949         }
4950     }
4951 }
4952
4953 /*!
4954  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
4955  * out of the cell.
4956  *  \throw If \a this->getMeshDimension() != 3.
4957  *  \throw If \a this->getSpaceDimension() != 3.
4958  *  \throw If the coordinates array is not set.
4959  *  \throw If the nodal connectivity of cells is not defined.
4960  *  \throw If the reparation fails.
4961  *
4962  *  \if ENABLE_EXAMPLES
4963  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
4964  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
4965  *  \endif
4966  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
4967  */
4968 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
4969 {
4970   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
4971     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
4972   mcIdType nbOfCells=getNumberOfCells();
4973   mcIdType *conn=_nodal_connec->getPointer();
4974   const mcIdType *connI=_nodal_connec_index->begin();
4975   const double *coordsPtr=_coords->begin();
4976   for(mcIdType i=0;i<nbOfCells;i++)
4977     {
4978       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
4979       if(type==INTERP_KERNEL::NORM_POLYHED)
4980         {
4981           try
4982           {
4983               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
4984                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
4985           }
4986           catch(INTERP_KERNEL::Exception& e)
4987           {
4988               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
4989               throw INTERP_KERNEL::Exception(oss.str());
4990           }
4991         }
4992     }
4993   updateTime();
4994 }
4995
4996 /*!
4997  * This method invert orientation of all cells in \a this.
4998  * After calling this method the absolute value of measure of cells in \a this are the same than before calling.
4999  * This method only operates on the connectivity so coordinates are not touched at all.
5000  */
5001 void MEDCouplingUMesh::invertOrientationOfAllCells()
5002 {
5003   checkConnectivityFullyDefined();
5004   std::set<INTERP_KERNEL::NormalizedCellType> gts(getAllGeoTypes());
5005   mcIdType *conn(_nodal_connec->getPointer());
5006   const mcIdType *conni(_nodal_connec_index->begin());
5007   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator gt=gts.begin();gt!=gts.end();gt++)
5008     {
5009       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::OrientationInverter> oi(INTERP_KERNEL::OrientationInverter::BuildInstanceFrom(*gt));
5010       MCAuto<DataArrayIdType> cwt(giveCellsWithType(*gt));
5011       for(const mcIdType *it=cwt->begin();it!=cwt->end();it++)
5012         oi->operate(conn+conni[*it]+1,conn+conni[*it+1]);
5013     }
5014   updateTime();
5015 }
5016
5017 /*!
5018  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5019  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5020  * according to which the first facet of the cell should be oriented to have the normal vector
5021  * pointing out of cell.
5022  *  \return DataArrayIdType * - a new instance of DataArrayIdType holding ids of fixed
5023  *         cells. The caller is to delete this array using decrRef() as it is no more
5024  *         needed.
5025  *  \throw If \a this->getMeshDimension() != 3.
5026  *  \throw If \a this->getSpaceDimension() != 3.
5027  *  \throw If the coordinates array is not set.
5028  *  \throw If the nodal connectivity of cells is not defined.
5029  *
5030  *  \if ENABLE_EXAMPLES
5031  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5032  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5033  *  \endif
5034  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5035  */
5036 DataArrayIdType *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5037 {
5038   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5039   if(getMeshDimension()!=3)
5040     throw INTERP_KERNEL::Exception(msg);
5041   int spaceDim=getSpaceDimension();
5042   if(spaceDim!=3)
5043     throw INTERP_KERNEL::Exception(msg);
5044   //
5045   mcIdType nbOfCells=getNumberOfCells();
5046   mcIdType *conn=_nodal_connec->getPointer();
5047   const mcIdType *connI=_nodal_connec_index->begin();
5048   const double *coo=getCoords()->begin();
5049   MCAuto<DataArrayIdType> cells(DataArrayIdType::New()); cells->alloc(0,1);
5050   for(mcIdType i=0;i<nbOfCells;i++)
5051     {
5052       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5053       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5054         {
5055           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5056             {
5057               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5058               cells->pushBackSilent(i);
5059             }
5060         }
5061     }
5062   return cells.retn();
5063 }
5064
5065 /*!
5066  * This method is a faster method to correct orientation of all 3D cells in \a this.
5067  * 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.
5068  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkConsistency should throw no exception.
5069  *
5070  * \return a newly allocated mcIdType array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5071  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5072  */
5073 DataArrayIdType *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
5074 {
5075   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5076     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5077   mcIdType nbOfCells=getNumberOfCells();
5078   mcIdType *conn=_nodal_connec->getPointer();
5079   const mcIdType *connI=_nodal_connec_index->begin();
5080   const double *coordsPtr=_coords->begin();
5081   MCAuto<DataArrayIdType> ret=DataArrayIdType::New(); ret->alloc(0,1);
5082   for(mcIdType i=0;i<nbOfCells;i++)
5083     {
5084       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5085       switch(type)
5086       {
5087         case INTERP_KERNEL::NORM_TETRA4:
5088           {
5089             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5090               {
5091                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5092                 ret->pushBackSilent(i);
5093               }
5094             break;
5095           }
5096         case INTERP_KERNEL::NORM_PYRA5:
5097           {
5098             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5099               {
5100                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5101                 ret->pushBackSilent(i);
5102               }
5103             break;
5104           }
5105         case INTERP_KERNEL::NORM_PENTA6:
5106         case INTERP_KERNEL::NORM_HEXA8:
5107         case INTERP_KERNEL::NORM_HEXGP12:
5108           {
5109             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5110               {
5111                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5112                 ret->pushBackSilent(i);
5113               }
5114             break;
5115           }
5116         case INTERP_KERNEL::NORM_POLYHED:
5117           {
5118             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5119               {
5120                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5121                 ret->pushBackSilent(i);
5122               }
5123             break;
5124           }
5125         default:
5126           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 !");
5127       }
5128     }
5129   updateTime();
5130   return ret.retn();
5131 }
5132
5133 /*!
5134  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5135  * If it is not the case an exception will be thrown.
5136  * This method is fast because the first cell of \a this is used to compute the plane.
5137  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5138  * \param pos output of size at least 3 used to store a point owned of searched plane.
5139  */
5140 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
5141 {
5142   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5143     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5144   const mcIdType *conn=_nodal_connec->begin();
5145   const mcIdType *connI=_nodal_connec_index->begin();
5146   const double *coordsPtr=_coords->begin();
5147   INTERP_KERNEL::areaVectorOfPolygon<mcIdType,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5148   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5149 }
5150
5151 /*!
5152  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5153  * cells. Currently cells of the following types are treated:
5154  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5155  * For a cell of other type an exception is thrown.
5156  * Space dimension of a 2D mesh can be either 2 or 3.
5157  * The Edge Ratio of a cell \f$t\f$ is:
5158  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5159  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5160  *  the smallest edge lengths of \f$t\f$.
5161  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5162  *          cells and one time, lying on \a this mesh. The caller is to delete this
5163  *          field using decrRef() as it is no more needed.
5164  *  \throw If the coordinates array is not set.
5165  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5166  *  \throw If the connectivity data array has more than one component.
5167  *  \throw If the connectivity data array has a named component.
5168  *  \throw If the connectivity index data array has more than one component.
5169  *  \throw If the connectivity index data array has a named component.
5170  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5171  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5172  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5173  */
5174 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
5175 {
5176   checkConsistencyLight();
5177   int spaceDim=getSpaceDimension();
5178   int meshDim=getMeshDimension();
5179   if(spaceDim!=2 && spaceDim!=3)
5180     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5181   if(meshDim!=2 && meshDim!=3)
5182     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5183   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5184   ret->setMesh(this);
5185   mcIdType nbOfCells=getNumberOfCells();
5186   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5187   arr->alloc(nbOfCells,1);
5188   double *pt=arr->getPointer();
5189   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5190   const mcIdType *conn=_nodal_connec->begin();
5191   const mcIdType *connI=_nodal_connec_index->begin();
5192   const double *coo=_coords->begin();
5193   double tmp[12];
5194   for(mcIdType i=0;i<nbOfCells;i++,pt++)
5195     {
5196       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5197       switch(t)
5198       {
5199         case INTERP_KERNEL::NORM_TRI3:
5200           {
5201             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5202             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5203             break;
5204           }
5205         case INTERP_KERNEL::NORM_QUAD4:
5206           {
5207             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5208             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5209             break;
5210           }
5211         case INTERP_KERNEL::NORM_TETRA4:
5212           {
5213             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5214             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5215             break;
5216           }
5217         default:
5218           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5219       }
5220       conn+=connI[i+1]-connI[i];
5221     }
5222   ret->setName("EdgeRatio");
5223   ret->synchronizeTimeWithSupport();
5224   return ret.retn();
5225 }
5226
5227 /*!
5228  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5229  * cells. Currently cells of the following types are treated:
5230  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5231  * For a cell of other type an exception is thrown.
5232  * Space dimension of a 2D mesh can be either 2 or 3.
5233  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5234  *          cells and one time, lying on \a this mesh. The caller is to delete this
5235  *          field using decrRef() as it is no more needed.
5236  *  \throw If the coordinates array is not set.
5237  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5238  *  \throw If the connectivity data array has more than one component.
5239  *  \throw If the connectivity data array has a named component.
5240  *  \throw If the connectivity index data array has more than one component.
5241  *  \throw If the connectivity index data array has a named component.
5242  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5243  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5244  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5245  */
5246 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
5247 {
5248   checkConsistencyLight();
5249   int spaceDim=getSpaceDimension();
5250   int meshDim=getMeshDimension();
5251   if(spaceDim!=2 && spaceDim!=3)
5252     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5253   if(meshDim!=2 && meshDim!=3)
5254     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5255   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5256   ret->setMesh(this);
5257   mcIdType nbOfCells=getNumberOfCells();
5258   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5259   arr->alloc(nbOfCells,1);
5260   double *pt=arr->getPointer();
5261   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5262   const mcIdType *conn=_nodal_connec->begin();
5263   const mcIdType *connI=_nodal_connec_index->begin();
5264   const double *coo=_coords->begin();
5265   double tmp[12];
5266   for(mcIdType i=0;i<nbOfCells;i++,pt++)
5267     {
5268       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5269       switch(t)
5270       {
5271         case INTERP_KERNEL::NORM_TRI3:
5272           {
5273             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5274             *pt=INTERP_KERNEL::triAspectRatio(tmp);
5275             break;
5276           }
5277         case INTERP_KERNEL::NORM_QUAD4:
5278           {
5279             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5280             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
5281             break;
5282           }
5283         case INTERP_KERNEL::NORM_TETRA4:
5284           {
5285             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5286             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
5287             break;
5288           }
5289         default:
5290           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5291       }
5292       conn+=connI[i+1]-connI[i];
5293     }
5294   ret->setName("AspectRatio");
5295   ret->synchronizeTimeWithSupport();
5296   return ret.retn();
5297 }
5298
5299 /*!
5300  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
5301  * cells of \a this 2D mesh in 3D space. It is a measure of the "planarity" of 2D cell
5302  * in 3D space. Currently only cells of the following types are
5303  * treated: INTERP_KERNEL::NORM_QUAD4.
5304  * For a cell of other type an exception is thrown.
5305  * The warp field is computed as follows: let (a,b,c,d) be the points of the quad.
5306  * Defining
5307  * \f$t=\vec{da}\times\vec{ab}\f$,
5308  * \f$u=\vec{ab}\times\vec{bc}\f$
5309  * \f$v=\vec{bc}\times\vec{cd}\f$
5310  * \f$w=\vec{cd}\times\vec{da}\f$, the warp is defined as \f$W^3\f$ with
5311  *  \f[
5312  *     W=min(\frac{t}{|t|}\cdot\frac{v}{|v|}, \frac{u}{|u|}\cdot\frac{w}{|w|})
5313  *  \f]
5314  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5315  *          cells and one time, lying on \a this mesh. The caller is to delete this
5316  *          field using decrRef() as it is no more needed.
5317  *  \throw If the coordinates array is not set.
5318  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5319  *  \throw If the connectivity data array has more than one component.
5320  *  \throw If the connectivity data array has a named component.
5321  *  \throw If the connectivity index data array has more than one component.
5322  *  \throw If the connectivity index data array has a named component.
5323  *  \throw If \a this->getMeshDimension() != 2.
5324  *  \throw If \a this->getSpaceDimension() != 3.
5325  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5326  */
5327 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
5328 {
5329   checkConsistencyLight();
5330   int spaceDim=getSpaceDimension();
5331   int meshDim=getMeshDimension();
5332   if(spaceDim!=3)
5333     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
5334   if(meshDim!=2)
5335     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
5336   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5337   ret->setMesh(this);
5338   mcIdType nbOfCells=getNumberOfCells();
5339   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5340   arr->alloc(nbOfCells,1);
5341   double *pt=arr->getPointer();
5342   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5343   const mcIdType *conn=_nodal_connec->begin();
5344   const mcIdType *connI=_nodal_connec_index->begin();
5345   const double *coo=_coords->begin();
5346   double tmp[12];
5347   for(mcIdType i=0;i<nbOfCells;i++,pt++)
5348     {
5349       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5350       switch(t)
5351       {
5352         case INTERP_KERNEL::NORM_QUAD4:
5353           {
5354             FillInCompact3DMode(3,4,conn+1,coo,tmp);
5355             *pt=INTERP_KERNEL::quadWarp(tmp);
5356             break;
5357           }
5358         default:
5359           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
5360       }
5361       conn+=connI[i+1]-connI[i];
5362     }
5363   ret->setName("Warp");
5364   ret->synchronizeTimeWithSupport();
5365   return ret.retn();
5366 }
5367
5368
5369 /*!
5370  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
5371  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
5372  * treated: INTERP_KERNEL::NORM_QUAD4.
5373  * The skew is computed as follow for a quad with points (a,b,c,d): let
5374  * \f$u=\vec{ab}+\vec{dc}\f$ and \f$v=\vec{ac}+\vec{bd}\f$
5375  * then the skew is computed as:
5376  *  \f[
5377  *    s=\frac{u}{|u|}\cdot\frac{v}{|v|}
5378  *  \f]
5379  *
5380  * For a cell of other type an exception is thrown.
5381  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5382  *          cells and one time, lying on \a this mesh. The caller is to delete this
5383  *          field using decrRef() as it is no more needed.
5384  *  \throw If the coordinates array is not set.
5385  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5386  *  \throw If the connectivity data array has more than one component.
5387  *  \throw If the connectivity data array has a named component.
5388  *  \throw If the connectivity index data array has more than one component.
5389  *  \throw If the connectivity index data array has a named component.
5390  *  \throw If \a this->getMeshDimension() != 2.
5391  *  \throw If \a this->getSpaceDimension() != 3.
5392  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5393  */
5394 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
5395 {
5396   checkConsistencyLight();
5397   int spaceDim=getSpaceDimension();
5398   int meshDim=getMeshDimension();
5399   if(spaceDim!=3)
5400     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
5401   if(meshDim!=2)
5402     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
5403   MCAuto<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5404   ret->setMesh(this);
5405   mcIdType nbOfCells=getNumberOfCells();
5406   MCAuto<DataArrayDouble> arr=DataArrayDouble::New();
5407   arr->alloc(nbOfCells,1);
5408   double *pt=arr->getPointer();
5409   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5410   const mcIdType *conn=_nodal_connec->begin();
5411   const mcIdType *connI=_nodal_connec_index->begin();
5412   const double *coo=_coords->begin();
5413   double tmp[12];
5414   for(mcIdType i=0;i<nbOfCells;i++,pt++)
5415     {
5416       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5417       switch(t)
5418       {
5419         case INTERP_KERNEL::NORM_QUAD4:
5420           {
5421             FillInCompact3DMode(3,4,conn+1,coo,tmp);
5422             *pt=INTERP_KERNEL::quadSkew(tmp);
5423             break;
5424           }
5425         default:
5426           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
5427       }
5428       conn+=connI[i+1]-connI[i];
5429     }
5430   ret->setName("Skew");
5431   ret->synchronizeTimeWithSupport();
5432   return ret.retn();
5433 }
5434
5435 /*!
5436  * Returns the cell field giving for each cell in \a this its diameter. Diameter means the max length of all possible SEG2 in the cell.
5437  *
5438  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
5439  *
5440  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
5441  */
5442 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
5443 {
5444   checkConsistencyLight();
5445   MCAuto<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
5446   ret->setMesh(this);
5447   std::set<INTERP_KERNEL::NormalizedCellType> types;
5448   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
5449   int spaceDim(getSpaceDimension());
5450   mcIdType nbCells(getNumberOfCells());
5451   MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
5452   arr->alloc(nbCells,1);
5453   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
5454     {
5455       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
5456       MCAuto<DataArrayIdType> cellIds(giveCellsWithType(*it));
5457       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
5458     }
5459   ret->setArray(arr);
5460   ret->setName("Diameter");
5461   return ret.retn();
5462 }
5463
5464 /*!
5465  * This method aggregate the bbox of each cell and put it into bbox parameter (xmin,xmax,ymin,ymax,zmin,zmax).
5466  *
5467  * \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)
5468  *                         For all other cases this input parameter is ignored.
5469  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5470  *
5471  * \throw If \a this is not fully set (coordinates and connectivity).
5472  * \throw If a cell in \a this has no valid nodeId.
5473  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
5474  */
5475 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
5476 {
5477   int mDim(getMeshDimension()),sDim(getSpaceDimension());
5478   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.
5479     return getBoundingBoxForBBTreeFast();
5480   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
5481     {
5482       bool presenceOfQuadratic(false);
5483       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
5484         {
5485           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
5486           if(cm.isQuadratic())
5487             presenceOfQuadratic=true;
5488         }
5489       if(!presenceOfQuadratic)
5490         return getBoundingBoxForBBTreeFast();
5491       if(mDim==2 && sDim==2)
5492         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
5493       else
5494         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
5495     }
5496   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) !");
5497 }
5498
5499 /*!
5500  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
5501  * So meshes having quadratic cells the computed bounding boxes can be invalid !
5502  *
5503  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5504  *
5505  * \throw If \a this is not fully set (coordinates and connectivity).
5506  * \throw If a cell in \a this has no valid nodeId.
5507  */
5508 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
5509 {
5510   checkFullyDefined();
5511   int spaceDim(getSpaceDimension());
5512   mcIdType nbOfCells(getNumberOfCells()), nbOfNodes(getNumberOfNodes());
5513   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5514   double *bbox(ret->getPointer());
5515   for(mcIdType i=0;i<nbOfCells*spaceDim;i++)
5516     {
5517       bbox[2*i]=std::numeric_limits<double>::max();
5518       bbox[2*i+1]=-std::numeric_limits<double>::max();
5519     }
5520   const double *coordsPtr(_coords->begin());
5521   const mcIdType *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5522   for(mcIdType i=0;i<nbOfCells;i++)
5523     {
5524       mcIdType offset=connI[i]+1;
5525       mcIdType nbOfNodesForCell(connI[i+1]-offset),kk(0);
5526       for(mcIdType j=0;j<nbOfNodesForCell;j++)
5527         {
5528           mcIdType nodeId=conn[offset+j];
5529           if(nodeId>=0 && nodeId<nbOfNodes)
5530             {
5531               for(int k=0;k<spaceDim;k++)
5532                 {
5533                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
5534                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
5535                 }
5536               kk++;
5537             }
5538         }
5539       if(kk==0)
5540         {
5541           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
5542           throw INTERP_KERNEL::Exception(oss.str());
5543         }
5544     }
5545   return ret.retn();
5546 }
5547
5548 /*!
5549  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
5550  * useful for 2D meshes having quadratic cells
5551  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
5552  * the two extremities of the arc of circle).
5553  *
5554  * \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)
5555  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5556  * \throw If \a this is not fully defined.
5557  * \throw If \a this is not a mesh with meshDimension equal to 2.
5558  * \throw If \a this is not a mesh with spaceDimension equal to 2.
5559  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
5560  */
5561 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
5562 {
5563   checkFullyDefined();
5564   INTERP_KERNEL::QuadraticPlanarPrecision arcPrec(arcDetEps);
5565
5566   int spaceDim(getSpaceDimension()),mDim(getMeshDimension());
5567   mcIdType nbOfCells=getNumberOfCells();
5568   if(spaceDim!=2 || mDim!=2)
5569     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!");
5570   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5571   double *bbox(ret->getPointer());
5572   const double *coords(_coords->begin());
5573   const mcIdType *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5574   for(mcIdType i=0;i<nbOfCells;i++,bbox+=4,connI++)
5575     {
5576       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
5577       mcIdType sz(connI[1]-connI[0]-1);
5578       std::vector<INTERP_KERNEL::Node *> nodes(sz);
5579       INTERP_KERNEL::QuadraticPolygon *pol(0);
5580       for(mcIdType j=0;j<sz;j++)
5581         {
5582           mcIdType nodeId(conn[*connI+1+j]);
5583           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
5584         }
5585       if(!cm.isQuadratic())
5586         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
5587       else
5588         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
5589       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
5590       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
5591     }
5592   return ret.retn();
5593 }
5594
5595 /*!
5596  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
5597  * useful for 2D meshes having quadratic cells
5598  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
5599  * the two extremities of the arc of circle).
5600  *
5601  * \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)
5602  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
5603  * \throw If \a this is not fully defined.
5604  * \throw If \a this is not a mesh with meshDimension equal to 1.
5605  * \throw If \a this is not a mesh with spaceDimension equal to 2.
5606  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
5607  */
5608 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
5609 {
5610   checkFullyDefined();
5611   int spaceDim(getSpaceDimension()),mDim(getMeshDimension());
5612   mcIdType nbOfCells=getNumberOfCells();
5613   if(spaceDim!=2 || mDim!=1)
5614     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!");
5615   INTERP_KERNEL::QuadraticPlanarPrecision arcPrec(arcDetEps);
5616   MCAuto<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
5617   double *bbox(ret->getPointer());
5618   const double *coords(_coords->begin());
5619   const mcIdType *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
5620   for(mcIdType i=0;i<nbOfCells;i++,bbox+=4,connI++)
5621     {
5622       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
5623       mcIdType sz(connI[1]-connI[0]-1);
5624       std::vector<INTERP_KERNEL::Node *> nodes(sz);
5625       INTERP_KERNEL::Edge *edge(0);
5626       for(mcIdType j=0;j<sz;j++)
5627         {
5628           mcIdType nodeId(conn[*connI+1+j]);
5629           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
5630         }
5631       if(!cm.isQuadratic())
5632         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
5633       else
5634         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
5635       const INTERP_KERNEL::Bounds& b(edge->getBounds());
5636       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
5637     }
5638   return ret.retn();
5639 }
5640
5641 /// @cond INTERNAL
5642
5643 namespace MEDCouplingImpl
5644 {
5645   class ConnReader
5646   {
5647   public:
5648     ConnReader(const mcIdType *c, mcIdType val):_conn(c),_val(val) { }
5649     bool operator() (const mcIdType& pos) { return _conn[pos]!=_val; }
5650   private:
5651     const mcIdType *_conn;
5652     mcIdType _val;
5653   };
5654
5655   class ConnReader2
5656   {
5657   public:
5658     ConnReader2(const mcIdType *c, mcIdType val):_conn(c),_val(val) { }
5659     bool operator() (const mcIdType& pos) { return _conn[pos]==_val; }
5660   private:
5661     const mcIdType *_conn;
5662     mcIdType _val;
5663   };
5664 }
5665
5666 /// @endcond
5667
5668 /*!
5669  * This method expects that \a this is sorted by types. If not an exception will be thrown.
5670  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
5671  * \a this is composed in cell types.
5672  * The returned array is of size 3*n where n is the number of different types present in \a this.
5673  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
5674  * This parameter is kept only for compatibility with other method listed above.
5675  */
5676 std::vector<mcIdType> MEDCouplingUMesh::getDistributionOfTypes() const
5677 {
5678   checkConnectivityFullyDefined();
5679   const mcIdType *conn=_nodal_connec->begin();
5680   const mcIdType *connI=_nodal_connec_index->begin();
5681   const mcIdType *work=connI;
5682   mcIdType nbOfCells=getNumberOfCells();
5683   std::size_t n=getAllGeoTypes().size();
5684   std::vector<mcIdType> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
5685   std::set<INTERP_KERNEL::NormalizedCellType> types;
5686   for(std::size_t i=0;work!=connI+nbOfCells;i++)
5687     {
5688       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
5689       if(types.find(typ)!=types.end())
5690         {
5691           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
5692           oss << " is not contiguous !";
5693           throw INTERP_KERNEL::Exception(oss.str());
5694         }
5695       types.insert(typ);
5696       ret[3*i]=typ;
5697       const mcIdType *work2=std::find_if(work+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,typ));
5698       ret[3*i+1]=ToIdType(std::distance(work,work2));
5699       work=work2;
5700     }
5701   return ret;
5702 }
5703
5704 /*!
5705  * This method is used to check that this has contiguous cell type in same order than described in \a code.
5706  * only for types cell, type node is not managed.
5707  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
5708  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
5709  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
5710  * If 2 or more same geometric type is in \a code and exception is thrown too.
5711  *
5712  * This method firstly checks
5713  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
5714  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
5715  * an exception is thrown too.
5716  *
5717  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
5718  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
5719  * and a DataArrayIdType instance is returned that the user has the responsibility to deallocate.
5720  */
5721 DataArrayIdType *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<mcIdType>& code, const std::vector<const DataArrayIdType *>& idsPerType) const
5722 {
5723   if(code.empty())
5724     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
5725   std::size_t sz=code.size();
5726   std::size_t n=sz/3;
5727   if(sz%3!=0)
5728     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
5729   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5730   mcIdType nb=0;
5731   bool isNoPflUsed=true;
5732   for(std::size_t i=0;i<n;i++)
5733     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
5734       {
5735         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
5736         nb+=code[3*i+1];
5737         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
5738           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
5739         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
5740       }
5741   if(types.size()!=n)
5742     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
5743   if(isNoPflUsed)
5744     {
5745       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
5746         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
5747       if(types.size()==_types.size())
5748         return 0;
5749     }
5750   MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
5751   ret->alloc(nb,1);
5752   mcIdType *retPtr=ret->getPointer();
5753   const mcIdType *connI=_nodal_connec_index->begin();
5754   const mcIdType *conn=_nodal_connec->begin();
5755   mcIdType nbOfCells=getNumberOfCells();
5756   const mcIdType *i=connI;
5757   int kk=0;
5758   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
5759     {
5760       i=std::find_if(i,connI+nbOfCells,MEDCouplingImpl::ConnReader2(conn,ToIdType((*it))));
5761       mcIdType offset=ToIdType(std::distance(connI,i));
5762       const mcIdType *j=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,ToIdType((*it))));
5763       mcIdType nbOfCellsOfCurType=ToIdType(std::distance(i,j));
5764       if(code[3*kk+2]==-1)
5765         for(mcIdType k=0;k<nbOfCellsOfCurType;k++)
5766           *retPtr++=k+offset;
5767       else
5768         {
5769           mcIdType idInIdsPerType=code[3*kk+2];
5770           if(idInIdsPerType>=0 && idInIdsPerType<ToIdType(idsPerType.size()))
5771             {
5772               const DataArrayIdType *zePfl=idsPerType[idInIdsPerType];
5773               if(zePfl)
5774                 {
5775                   zePfl->checkAllocated();
5776                   if(zePfl->getNumberOfComponents()==1)
5777                     {
5778                       for(const mcIdType *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
5779                         {
5780                           if(*k>=0 && *k<nbOfCellsOfCurType)
5781                             *retPtr=(*k)+offset;
5782                           else
5783                             {
5784                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
5785                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
5786                               throw INTERP_KERNEL::Exception(oss.str());
5787                             }
5788                         }
5789                     }
5790                   else
5791                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
5792                 }
5793               else
5794                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
5795             }
5796           else
5797             {
5798               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
5799               oss << " should be in [0," << idsPerType.size() << ") !";
5800               throw INTERP_KERNEL::Exception(oss.str());
5801             }
5802         }
5803       i=j;
5804     }
5805   return ret.retn();
5806 }
5807
5808 /*!
5809  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
5810  * 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.
5811  * 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.
5812  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
5813  *
5814  * \param [in] profile
5815  * \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.
5816  * \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,
5817  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
5818  * \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.
5819  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
5820  * \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
5821  */
5822 void MEDCouplingUMesh::splitProfilePerType(const DataArrayIdType *profile, std::vector<mcIdType>& code, std::vector<DataArrayIdType *>& idsInPflPerType, std::vector<DataArrayIdType *>& idsPerType, bool smartPflKiller) const
5823 {
5824   if(!profile)
5825     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
5826   if(profile->getNumberOfComponents()!=1)
5827     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
5828   checkConnectivityFullyDefined();
5829   const mcIdType *conn=_nodal_connec->begin();
5830   const mcIdType *connI=_nodal_connec_index->begin();
5831   mcIdType nbOfCells=getNumberOfCells();
5832   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5833   std::vector<mcIdType> typeRangeVals(1);
5834   for(const mcIdType *i=connI;i!=connI+nbOfCells;)
5835     {
5836       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5837       if(std::find(types.begin(),types.end(),curType)!=types.end())
5838         {
5839           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
5840         }
5841       types.push_back(curType);
5842       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,ToIdType(curType)));
5843       typeRangeVals.push_back(ToIdType(std::distance(connI,i)));
5844     }
5845   //
5846   DataArrayIdType *castArr=0,*rankInsideCast=0,*castsPresent=0;
5847   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
5848   MCAuto<DataArrayIdType> tmp0=castArr;
5849   MCAuto<DataArrayIdType> tmp1=rankInsideCast;
5850   MCAuto<DataArrayIdType> tmp2=castsPresent;
5851   //
5852   mcIdType nbOfCastsFinal=castsPresent->getNumberOfTuples();
5853   code.resize(3*nbOfCastsFinal);
5854   std::vector< MCAuto<DataArrayIdType> > idsInPflPerType2;
5855   std::vector< MCAuto<DataArrayIdType> > idsPerType2;
5856   for(mcIdType i=0;i<nbOfCastsFinal;i++)
5857     {
5858       mcIdType castId=castsPresent->getIJ(i,0);
5859       MCAuto<DataArrayIdType> tmp3=castArr->findIdsEqual(castId);
5860       idsInPflPerType2.push_back(tmp3);
5861       code[3*i]=ToIdType(types[castId]);
5862       code[3*i+1]=tmp3->getNumberOfTuples();
5863       MCAuto<DataArrayIdType> tmp4=rankInsideCast->selectByTupleId(tmp3->begin(),tmp3->begin()+tmp3->getNumberOfTuples());
5864       if(!smartPflKiller || !tmp4->isIota(typeRangeVals[castId+1]-typeRangeVals[castId]))
5865         {
5866           tmp4->copyStringInfoFrom(*profile);
5867           idsPerType2.push_back(tmp4);
5868           code[3*i+2]=ToIdType(idsPerType2.size())-1;
5869         }
5870       else
5871         {
5872           code[3*i+2]=-1;
5873         }
5874     }
5875   std::size_t sz2=idsInPflPerType2.size();
5876   idsInPflPerType.resize(sz2);
5877   for(std::size_t i=0;i<sz2;i++)
5878     {
5879       DataArrayIdType *locDa=idsInPflPerType2[i];
5880       locDa->incrRef();
5881       idsInPflPerType[i]=locDa;
5882     }
5883   std::size_t sz=idsPerType2.size();
5884   idsPerType.resize(sz);
5885   for(std::size_t i=0;i<sz;i++)
5886     {
5887       DataArrayIdType *locDa=idsPerType2[i];
5888       locDa->incrRef();
5889       idsPerType[i]=locDa;
5890     }
5891 }
5892
5893 /*!
5894  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
5895  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
5896  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
5897  * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as MEDCoupling::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.
5898  */
5899 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayIdType *desc, DataArrayIdType *descIndx, DataArrayIdType *&revDesc, DataArrayIdType *&revDescIndx, DataArrayIdType *& nM1LevMeshIds, DataArrayIdType *&meshnM1Old2New) const
5900 {
5901   checkFullyDefined();
5902   nM1LevMesh->checkFullyDefined();
5903   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
5904     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
5905   if(_coords!=nM1LevMesh->getCoords())
5906     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
5907   MCAuto<DataArrayIdType> tmp0=DataArrayIdType::New();
5908   MCAuto<DataArrayIdType> tmp1=DataArrayIdType::New();
5909   MCAuto<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
5910   MCAuto<DataArrayIdType> ret0=ret1->sortCellsInMEDFileFrmt();
5911   desc->transformWithIndArr(ret0->begin(),ret0->begin()+ret0->getNbOfElems());
5912   MCAuto<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5913   tmp->setConnectivity(tmp0,tmp1);
5914   tmp->renumberCells(ret0->begin(),false);
5915   revDesc=tmp->getNodalConnectivity();
5916   revDescIndx=tmp->getNodalConnectivityIndex();
5917   DataArrayIdType *ret=0;
5918   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
5919     {
5920       mcIdType tmp2;
5921       ret->getMaxValue(tmp2);
5922       ret->decrRef();
5923       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
5924       throw INTERP_KERNEL::Exception(oss.str());
5925     }
5926   nM1LevMeshIds=ret;
5927   //
5928   revDesc->incrRef();
5929   revDescIndx->incrRef();
5930   ret1->incrRef();
5931   ret0->incrRef();
5932   meshnM1Old2New=ret0;
5933   return ret1;
5934 }
5935
5936 /*!
5937  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
5938  * necessary for writing the mesh to MED file. Additionally returns a permutation array
5939  * in "Old to New" mode.
5940  *  \return DataArrayIdType * - a new instance of DataArrayIdType. The caller is to delete
5941  *          this array using decrRef() as it is no more needed.
5942  *  \throw If the nodal connectivity of cells is not defined.
5943  */
5944 DataArrayIdType *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
5945 {
5946   checkConnectivityFullyDefined();
5947   MCAuto<DataArrayIdType> ret=getRenumArrForMEDFileFrmt();
5948   renumberCells(ret->begin(),false);
5949   return ret.retn();
5950 }
5951
5952 /*!
5953  * This methods checks that cells are sorted by their types.
5954  * This method makes asumption (no check) that connectivity is correctly set before calling.
5955  */
5956 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
5957 {
5958   checkFullyDefined();
5959   const mcIdType *conn=_nodal_connec->begin();
5960   const mcIdType *connI=_nodal_connec_index->begin();
5961   mcIdType nbOfCells=getNumberOfCells();
5962   std::set<INTERP_KERNEL::NormalizedCellType> types;
5963   for(const mcIdType *i=connI;i!=connI+nbOfCells;)
5964     {
5965       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5966       if(types.find(curType)!=types.end())
5967         return false;
5968       types.insert(curType);
5969       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,ToIdType(curType)));
5970     }
5971   return true;
5972 }
5973
5974 /*!
5975  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
5976  * The geometric type order is specified by MED file.
5977  *
5978  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
5979  */
5980 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
5981 {
5982   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
5983 }
5984
5985 /*!
5986  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
5987  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
5988  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
5989  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
5990  */
5991 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
5992 {
5993   checkFullyDefined();
5994   const mcIdType *conn=_nodal_connec->begin();
5995   const mcIdType *connI=_nodal_connec_index->begin();
5996   mcIdType nbOfCells=getNumberOfCells();
5997   if(nbOfCells==0)
5998     return true;
5999   mcIdType lastPos=-1;
6000   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6001   for(const mcIdType *i=connI;i!=connI+nbOfCells;)
6002     {
6003       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6004       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6005       if(isTypeExists!=orderEnd)
6006         {
6007           mcIdType pos=ToIdType(std::distance(orderBg,isTypeExists));
6008           if(pos<=lastPos)
6009             return false;
6010           lastPos=pos;
6011           i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,ToIdType(curType)));
6012         }
6013       else
6014         {
6015           if(sg.find(curType)==sg.end())
6016             {
6017               i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,ToIdType(curType)));
6018               sg.insert(curType);
6019             }
6020           else
6021             return false;
6022         }
6023     }
6024   return true;
6025 }
6026
6027 /*!
6028  * This method returns 2 newly allocated DataArrayIdType instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6029  * 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
6030  * number of tuples than input type array and with one component. This 2nd output array gives type by type the number of occurrence of type in 'this'.
6031  */
6032 DataArrayIdType *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayIdType *&nbPerType) const
6033 {
6034   checkConnectivityFullyDefined();
6035   mcIdType nbOfCells=getNumberOfCells();
6036   const mcIdType *conn=_nodal_connec->begin();
6037   const mcIdType *connI=_nodal_connec_index->begin();
6038   MCAuto<DataArrayIdType> tmpa=DataArrayIdType::New();
6039   MCAuto<DataArrayIdType> tmpb=DataArrayIdType::New();
6040   tmpa->alloc(nbOfCells,1);
6041   tmpb->alloc(std::distance(orderBg,orderEnd),1);
6042   tmpb->fillWithZero();
6043   mcIdType *tmp=tmpa->getPointer();
6044   mcIdType *tmp2=tmpb->getPointer();
6045   for(const mcIdType *i=connI;i!=connI+nbOfCells;i++)
6046     {
6047       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6048       if(where!=orderEnd)
6049         {
6050           mcIdType pos=ToIdType(std::distance(orderBg,where));
6051           tmp2[pos]++;
6052           tmp[std::distance(connI,i)]=pos;
6053         }
6054       else
6055         {
6056           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6057           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6058           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6059           throw INTERP_KERNEL::Exception(oss.str());
6060         }
6061     }
6062   nbPerType=tmpb.retn();
6063   return tmpa.retn();
6064 }
6065
6066 /*!
6067  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6068  *
6069  * \return a new object containing the old to new correspondence.
6070  *
6071  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6072  */
6073 DataArrayIdType *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6074 {
6075   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6076 }
6077
6078 /*!
6079  * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specified by [ \a orderBg , \a orderEnd ) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in \a this.
6080  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6081  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6082  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6083  */
6084 DataArrayIdType *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6085 {
6086   DataArrayIdType *nbPerType=0;
6087   MCAuto<DataArrayIdType> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6088   nbPerType->decrRef();
6089   return tmpa->buildPermArrPerLevel();
6090 }
6091
6092 /*!
6093  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6094  * The number of cells remains unchanged after the call of this method.
6095  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6096  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6097  *
6098  * \return the array giving the correspondence old to new.
6099  */
6100 DataArrayIdType *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6101 {
6102   checkFullyDefined();
6103   computeTypes();
6104   const mcIdType *conn=_nodal_connec->begin();
6105   const mcIdType *connI=_nodal_connec_index->begin();
6106   mcIdType nbOfCells=getNumberOfCells();
6107   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6108   for(const mcIdType *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6109     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6110       {
6111         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6112         types.push_back(curType);
6113         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6114       }
6115   DataArrayIdType *ret=DataArrayIdType::New();
6116   ret->alloc(nbOfCells,1);
6117   mcIdType *retPtr=ret->getPointer();
6118   std::fill(retPtr,retPtr+nbOfCells,-1);
6119   mcIdType newCellId=0;
6120   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6121     {
6122       for(const mcIdType *i=connI;i!=connI+nbOfCells;i++)
6123         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6124           retPtr[std::distance(connI,i)]=newCellId++;
6125     }
6126   renumberCells(retPtr,false);
6127   return ret;
6128 }
6129
6130 /*!
6131  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6132  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6133  * This method makes asumption that connectivity is correctly set before calling.
6134  */
6135 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6136 {
6137   checkConnectivityFullyDefined();
6138   const mcIdType *conn=_nodal_connec->begin();
6139   const mcIdType *connI=_nodal_connec_index->begin();
6140   mcIdType nbOfCells=getNumberOfCells();
6141   std::vector<MEDCouplingUMesh *> ret;
6142   for(const mcIdType *i=connI;i!=connI+nbOfCells;)
6143     {
6144       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6145       mcIdType beginCellId=ToIdType(std::distance(connI,i));
6146       i=std::find_if(i+1,connI+nbOfCells,MEDCouplingImpl::ConnReader(conn,ToIdType(curType)));
6147       mcIdType endCellId=ToIdType(std::distance(connI,i));
6148       mcIdType sz=endCellId-beginCellId;
6149       mcIdType *cells=new mcIdType[sz];
6150       for(mcIdType j=0;j<sz;j++)
6151         cells[j]=beginCellId+j;
6152       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6153       delete [] cells;
6154       ret.push_back(m);
6155     }
6156   return ret;
6157 }
6158
6159 /*!
6160  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6161  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6162  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6163  *
6164  * \return a newly allocated instance, that the caller must manage.
6165  * \throw If \a this contains more than one geometric type.
6166  * \throw If the nodal connectivity of \a this is not fully defined.
6167  * \throw If the internal data is not coherent.
6168  */
6169 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
6170 {
6171   checkConnectivityFullyDefined();
6172   if(_types.size()!=1)
6173     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6174   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6175   MCAuto<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6176   ret->setCoords(getCoords());
6177   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6178   if(retC)
6179     {
6180       MCAuto<DataArrayIdType> c=convertNodalConnectivityToStaticGeoTypeMesh();
6181       retC->setNodalConnectivity(c);
6182     }
6183   else
6184     {
6185       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6186       if(!retD)
6187         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6188       DataArrayIdType *c=0,*ci=0;
6189       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6190       MCAuto<DataArrayIdType> cs(c),cis(ci);
6191       retD->setNodalConnectivity(cs,cis);
6192     }
6193   return ret.retn();
6194 }
6195
6196 DataArrayIdType *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
6197 {
6198   checkConnectivityFullyDefined();
6199   if(_types.size()!=1)
6200     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6201   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6202   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6203   if(cm.isDynamic())
6204     {
6205       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6206       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6207       throw INTERP_KERNEL::Exception(oss.str());
6208     }
6209   mcIdType nbCells=getNumberOfCells();
6210   mcIdType typi=ToIdType(typ);
6211   mcIdType nbNodesPerCell=ToIdType(cm.getNumberOfNodes());
6212   MCAuto<DataArrayIdType> connOut=DataArrayIdType::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6213   mcIdType *outPtr=connOut->getPointer();
6214   const mcIdType *conn=_nodal_connec->begin();
6215   const mcIdType *connI=_nodal_connec_index->begin();
6216   nbNodesPerCell++;
6217   for(mcIdType i=0;i<nbCells;i++,connI++)
6218     {
6219       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6220         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6221       else
6222         {
6223           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 << ") !";
6224           throw INTERP_KERNEL::Exception(oss.str());
6225         }
6226     }
6227   return connOut.retn();
6228 }
6229
6230 /*!
6231  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
6232  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
6233  * \param nodalConn
6234  * \param nodalConnI
6235  */
6236 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayIdType *&nodalConn, DataArrayIdType *&nodalConnIndex) const
6237 {
6238   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkConsistency !";
6239   checkConnectivityFullyDefined();
6240   if(_types.size()!=1)
6241     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6242   mcIdType nbCells=getNumberOfCells(),
6243            lgth=_nodal_connec->getNumberOfTuples();
6244   if(lgth<nbCells)
6245     throw INTERP_KERNEL::Exception(msg0);
6246   MCAuto<DataArrayIdType> c(DataArrayIdType::New()),ci(DataArrayIdType::New());
6247   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6248   mcIdType *cp(c->getPointer()),*cip(ci->getPointer());
6249   const mcIdType *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6250   cip[0]=0;
6251   for(mcIdType i=0;i<nbCells;i++,cip++,incip++)
6252     {
6253       mcIdType strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6254       mcIdType delta(stop-strt);
6255       if(delta>=1)
6256         {
6257           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6258             cp=std::copy(incp+strt,incp+stop,cp);
6259           else
6260             throw INTERP_KERNEL::Exception(msg0);
6261         }
6262       else
6263         throw INTERP_KERNEL::Exception(msg0);
6264       cip[1]=cip[0]+delta;
6265     }
6266   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6267 }
6268
6269 /*!
6270  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6271  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6272  * This method is particularly useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6273  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6274  * are not used here to avoid the build of big permutation array.
6275  *
6276  * \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
6277  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6278  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayIdType instance whose number of tuples is equal to the number of chunks of same geotype
6279  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6280  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayIdType instance having the same size than \b szOfCellGrpOfSameType. This
6281  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6282  * \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
6283  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6284  */
6285 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6286                                                                             DataArrayIdType *&szOfCellGrpOfSameType,
6287                                                                             DataArrayIdType *&idInMsOfCellGrpOfSameType)
6288 {
6289   std::vector<const MEDCouplingUMesh *> ms2;
6290   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6291     if(*it)
6292       {
6293         (*it)->checkConnectivityFullyDefined();
6294         ms2.push_back(*it);
6295       }
6296   if(ms2.empty())
6297     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6298   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6299   int meshDim=ms2[0]->getMeshDimension();
6300   std::vector<const MEDCouplingUMesh *> m1ssm;
6301   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmAuto;
6302   //
6303   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6304   std::vector< MCAuto<MEDCouplingUMesh> > m1ssmSingleAuto;
6305   mcIdType fake=0,rk=0;
6306   MCAuto<DataArrayIdType> ret1(DataArrayIdType::New()),ret2(DataArrayIdType::New());
6307   ret1->alloc(0,1); ret2->alloc(0,1);
6308   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6309     {
6310       if(meshDim!=(*it)->getMeshDimension())
6311         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6312       if(refCoo!=(*it)->getCoords())
6313         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6314       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6315       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6316       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MCAuto<MEDCouplingUMesh> > >(m1ssmAuto));
6317       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6318         {
6319           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6320           m1ssmSingleAuto.push_back(singleCell);
6321           m1ssmSingle.push_back(singleCell);
6322           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6323         }
6324     }
6325   MCAuto<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6326   MCAuto<DataArrayIdType> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6327   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6328   for(mcIdType i=0;i<ToIdType(m1ssm.size());i++)
6329     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6330   MCAuto<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6331   szOfCellGrpOfSameType=ret1->renumber(renum->begin());
6332   idInMsOfCellGrpOfSameType=ret2->renumber(renum->begin());
6333   return ret0.retn();
6334 }
6335
6336 /*!
6337  * This method returns a newly created DataArrayIdType instance.
6338  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6339  */
6340 DataArrayIdType *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const mcIdType *begin, const mcIdType *end) const
6341 {
6342   checkFullyDefined();
6343   const mcIdType *conn=_nodal_connec->begin();
6344   const mcIdType *connIndex=_nodal_connec_index->begin();
6345   MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(0,1);
6346   for(const mcIdType *w=begin;w!=end;w++)
6347     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6348       ret->pushBackSilent(*w);
6349   return ret.retn();
6350 }
6351
6352 /*!
6353  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6354  * are in [0:getNumberOfCells())
6355  */
6356 DataArrayIdType *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayIdType *da) const
6357 {
6358   checkFullyDefined();
6359   const mcIdType *conn=_nodal_connec->begin();
6360   const mcIdType *connI=_nodal_connec_index->begin();
6361   mcIdType nbOfCells=getNumberOfCells();
6362   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
6363   mcIdType *tmp=new mcIdType[nbOfCells];
6364   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6365     {
6366       mcIdType j=0;
6367       for(const mcIdType *i=connI;i!=connI+nbOfCells;i++)
6368         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6369           tmp[std::distance(connI,i)]=j++;
6370     }
6371   DataArrayIdType *ret=DataArrayIdType::New();
6372   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6373   ret->copyStringInfoFrom(*da);
6374   mcIdType *retPtr=ret->getPointer();
6375   const mcIdType *daPtr=da->begin();
6376   mcIdType nbOfElems=da->getNbOfElems();
6377   for(mcIdType k=0;k<nbOfElems;k++)
6378     retPtr[k]=tmp[daPtr[k]];
6379   delete [] tmp;
6380   return ret;
6381 }
6382
6383 /*!
6384  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6385  * This method \b works \b for mesh sorted by type.
6386  * cells whose ids is in 'idsPerGeoType' array.
6387  * This method conserves coords and name of mesh.
6388  */
6389 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const mcIdType *idsPerGeoTypeBg, const mcIdType *idsPerGeoTypeEnd) const
6390 {
6391   std::vector<mcIdType> code=getDistributionOfTypes();
6392   std::size_t nOfTypesInThis=code.size()/3;
6393   mcIdType sz=0,szOfType=0;
6394   for(std::size_t i=0;i<nOfTypesInThis;i++)
6395     {
6396       if(code[3*i]!=type)
6397         sz+=code[3*i+1];
6398       else
6399         szOfType=code[3*i+1];
6400     }
6401   for(const mcIdType *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6402     if(*work<0 || *work>=szOfType)
6403       {
6404         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6405         oss << ". It should be in [0," << szOfType << ") !";
6406         throw INTERP_KERNEL::Exception(oss.str());
6407       }
6408   MCAuto<DataArrayIdType> idsTokeep=DataArrayIdType::New(); idsTokeep->alloc(sz+std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6409   mcIdType *idsPtr=idsTokeep->getPointer();
6410   mcIdType offset=0;
6411   for(std::size_t i=0;i<nOfTypesInThis;i++)
6412     {
6413       if(code[3*i]!=type)
6414         for(mcIdType j=0;j<code[3*i+1];j++)
6415           *idsPtr++=offset+j;
6416       else
6417         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<mcIdType>(),offset));
6418       offset+=code[3*i+1];
6419     }
6420   MCAuto<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6421   ret->copyTinyInfoFrom(this);
6422   return ret.retn();
6423 }
6424
6425 /*!
6426  * This method returns a vector of size 'this->getNumberOfCells()'.
6427  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6428  */
6429 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
6430 {
6431   mcIdType ncell=getNumberOfCells();
6432   std::vector<bool> ret(ncell);
6433   const mcIdType *cI=getNodalConnectivityIndex()->begin();
6434   const mcIdType *c=getNodalConnectivity()->begin();
6435   for(mcIdType i=0;i<ncell;i++)
6436     {
6437       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6438       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6439       ret[i]=cm.isQuadratic();
6440     }
6441   return ret;
6442 }
6443
6444 /*!
6445  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6446  */
6447 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6448 {
6449   if(other->getType()!=UNSTRUCTURED)
6450     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6451   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6452   return MergeUMeshes(this,otherC);
6453 }
6454
6455 /*!
6456  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6457  * computed by averaging coordinates of cell nodes, so this method is not a right
6458  * choice for degenerated meshes (not well oriented, cells with measure close to zero).
6459  * Beware also that for quadratic meshes, degenerated arc of circles are turned into linear edges for the computation.
6460  * This happens with a default detection precision of eps=1.0e-14. If you need control over this use computeCellCenterOfMassWithPrecision().
6461  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6462  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6463  *          components. The caller is to delete this array using decrRef() as it is
6464  *          no more needed.
6465  *  \throw If the coordinates array is not set.
6466  *  \throw If the nodal connectivity of cells is not defined.
6467  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6468  *  \sa MEDCouplingUMesh::computeCellCenterOfMassWithPrecision
6469  */
6470 DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMass() const
6471 {
6472   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
6473   int spaceDim=getSpaceDimension();
6474   mcIdType nbOfCells=getNumberOfCells();
6475   ret->alloc(nbOfCells,spaceDim);
6476   ret->copyStringInfoFrom(*getCoords());
6477   double *ptToFill=ret->getPointer();
6478   const mcIdType *nodal=_nodal_connec->begin();
6479   const mcIdType *nodalI=_nodal_connec_index->begin();
6480   const double *coor=_coords->begin();
6481   for(mcIdType i=0;i<nbOfCells;i++)
6482     {
6483       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6484       INTERP_KERNEL::computeBarycenter2<mcIdType,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6485       ptToFill+=spaceDim;
6486     }
6487   return ret.retn();
6488 }
6489
6490
6491 /*!
6492  * See computeCellCenterOfMass().
6493  *  \param eps a precision for the detection of degenerated arc of circles.
6494  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6495  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6496  *          components. The caller is to delete this array using decrRef() as it is
6497  *          no more needed.
6498  *  \throw If the coordinates array is not set.
6499  *  \throw If the nodal connectivity of cells is not defined.
6500  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6501  *  \sa MEDCouplingUMesh::computeCellCenterOfMassWithPrecision
6502  */
6503 DataArrayDouble *MEDCouplingUMesh::computeCellCenterOfMassWithPrecision(double eps) const
6504 {
6505   INTERP_KERNEL::QuadraticPlanarPrecision prec(eps);
6506   MCAuto<DataArrayDouble> ret = computeCellCenterOfMass();
6507   return ret.retn();
6508 }
6509
6510
6511 /*!
6512  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
6513  * the cell. Contrary to badly named MEDCouplingUMesh::computeCellCenterOfMass method that returns the center of inertia of the
6514  *
6515  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
6516  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
6517  *
6518  * \sa MEDCouplingUMesh::computeCellCenterOfMass
6519  * \throw If \a this is not fully defined (coordinates and connectivity)
6520  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
6521  */
6522 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
6523 {
6524   checkFullyDefined();
6525   MCAuto<DataArrayDouble> ret=DataArrayDouble::New();
6526   int spaceDim=getSpaceDimension();
6527   mcIdType nbOfCells=getNumberOfCells();
6528   mcIdType nbOfNodes=getNumberOfNodes();
6529   ret->alloc(nbOfCells,spaceDim);
6530   double *ptToFill=ret->getPointer();
6531   const mcIdType *nodal=_nodal_connec->begin();
6532   const mcIdType *nodalI=_nodal_connec_index->begin();
6533   const double *coor=_coords->begin();
6534   for(mcIdType i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
6535     {
6536       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6537       std::fill(ptToFill,ptToFill+spaceDim,0.);
6538       if(type!=INTERP_KERNEL::NORM_POLYHED)
6539         {
6540           for(const mcIdType *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
6541             {
6542               if(*conn>=0 && *conn<nbOfNodes)
6543                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
6544               else
6545                 {
6546                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
6547                   throw INTERP_KERNEL::Exception(oss.str());
6548                 }
6549             }
6550           mcIdType nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
6551           if(nbOfNodesInCell>0)
6552             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6553           else
6554             {
6555               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
6556               throw INTERP_KERNEL::Exception(oss.str());
6557             }
6558         }
6559       else
6560         {
6561           std::set<mcIdType> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
6562           s.erase(-1);
6563           for(std::set<mcIdType>::const_iterator it=s.begin();it!=s.end();it++)
6564             {
6565               if(*it>=0 && *it<nbOfNodes)
6566                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
6567               else
6568                 {
6569                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
6570                   throw INTERP_KERNEL::Exception(oss.str());
6571                 }
6572             }
6573           if(!s.empty())
6574             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
6575           else
6576             {
6577               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
6578               throw INTERP_KERNEL::Exception(oss.str());
6579             }
6580         }
6581     }
6582   return ret.retn();
6583 }
6584
6585 /*!
6586  * Returns a new DataArrayDouble holding barycenters of specified cells. The
6587  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
6588  * are specified via an array of cell ids.
6589  *  \warning Validity of the specified cell ids is not checked!
6590  *           Valid range is [ 0, \a this->getNumberOfCells() ).
6591  *  \param [in] begin - an array of cell ids of interest.
6592  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
6593  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
6594  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
6595  *          caller is to delete this array using decrRef() as it is no more needed.
6596  *  \throw If the coordinates array is not set.
6597  *  \throw If the nodal connectivity of cells is not defined.
6598  *
6599  *  \if ENABLE_EXAMPLES
6600  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
6601  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
6602  *  \endif
6603  */
6604 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const mcIdType *begin, const mcIdType *end) const
6605 {
6606   DataArrayDouble *ret=DataArrayDouble::New();
6607   int spaceDim=getSpaceDimension();
6608   std::size_t nbOfTuple=std::distance(begin,end);
6609   ret->alloc(nbOfTuple,spaceDim);
6610   double *ptToFill=ret->getPointer();
6611   double *tmp=new double[spaceDim];
6612   const mcIdType *nodal=_nodal_connec->begin();
6613   const mcIdType *nodalI=_nodal_connec_index->begin();
6614   const double *coor=_coords->begin();
6615   for(const mcIdType *w=begin;w!=end;w++)
6616     {
6617       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
6618       INTERP_KERNEL::computeBarycenter2<mcIdType,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
6619       ptToFill+=spaceDim;
6620     }
6621   delete [] tmp;
6622   return ret;
6623 }
6624
6625 /*!
6626  * 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".
6627  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
6628  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
6629  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
6630  * This method is useful to detect 2D cells in 3D space that are not coplanar.
6631  *
6632  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
6633  * \throw If spaceDim!=3 or meshDim!=2.
6634  * \throw If connectivity of \a this is invalid.
6635  * \throw If connectivity of a cell in \a this points to an invalid node.
6636  */
6637 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
6638 {
6639   MCAuto<DataArrayDouble> ret(DataArrayDouble::New());
6640   mcIdType nbOfCells=getNumberOfCells();
6641   mcIdType nbOfNodes(getNumberOfNodes());
6642   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
6643     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
6644   ret->alloc(nbOfCells,4);
6645   double *retPtr(ret->getPointer());
6646   const mcIdType *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
6647   const double *coor(_coords->begin());
6648   for(mcIdType i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
6649     {
6650       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
6651       if(nodalI[1]-nodalI[0]>=4)
6652         {
6653           double aa[3]={coor[nodal[nodalI[0]+1+1]*3+0]-coor[nodal[nodalI[0]+1+0]*3+0],
6654                         coor[nodal[nodalI[0]+1+1]*3+1]-coor[nodal[nodalI[0]+1+0]*3+1],
6655                         coor[nodal[nodalI[0]+1+1]*3+2]-coor[nodal[nodalI[0]+1+0]*3+2]}
6656           ,bb[3]={coor[nodal[nodalI[0]+1+2]*3+0]-coor[nodal[nodalI[0]+1+0]*3+0],
6657                         coor[nodal[nodalI[0]+1+2]*3+1]-coor[nodal[nodalI[0]+1+0]*3+1],
6658                         coor[nodal[nodalI[0]+1+2]*3+2]-coor[nodal[nodalI[0]+1+0]*3+2]};
6659           double cc[3]={aa[1]*bb[2]-aa[2]*bb[1],aa[2]*bb[0]-aa[0]*bb[2],aa[0]*bb[1]-aa[1]*bb[0]};
6660           double aa_norm(sqrt(aa[0]*aa[0]+aa[1]*aa[1]+aa[2]*aa[2])),bb_norm(sqrt(bb[0]*bb[0]+bb[1]*bb[1]+bb[2]*bb[2]));
6661           for(int j=0;j<3;j++)
6662             {
6663               mcIdType nodeId(nodal[nodalI[0]+1+j]);
6664               if(nodeId>=0 && nodeId<nbOfNodes)
6665                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
6666               else
6667                 {
6668                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
6669                   throw INTERP_KERNEL::Exception(oss.str());
6670                 }
6671             }
6672           if(sqrt(cc[0]*cc[0]+cc[1]*cc[1]+cc[2]*cc[2])>(1e-3*aa_norm*bb_norm))
6673             {
6674               INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
6675               retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
6676             }
6677           else
6678             {
6679               if(nodalI[1]-nodalI[0]==4)
6680                 {
6681                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : cell" << i << " : Presence of The 3 colinear points !";
6682                   throw INTERP_KERNEL::Exception(oss.str());
6683                 }
6684               //
6685               double dd[3]={0.,0.,0.};
6686               for(mcIdType offset=nodalI[0]+1;offset<nodalI[1];offset++)
6687                 std::transform(coor+3*nodal[offset],coor+3*(nodal[offset]+1),dd,dd,std::plus<double>());
6688               mcIdType nbOfNodesInCell(nodalI[1]-nodalI[0]-1);
6689               std::transform(dd,dd+3,dd,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6690               std::copy(dd,dd+3,matrix+4*2);
6691               INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
6692               retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
6693             }
6694         }
6695       else
6696         {
6697           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
6698           throw INTERP_KERNEL::Exception(oss.str());
6699         }
6700     }
6701   return ret.retn();
6702 }
6703
6704 /*!
6705  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
6706  *
6707  */
6708 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
6709 {
6710   if(!da)
6711     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
6712   da->checkAllocated();
6713   std::string name(da->getName());
6714   MCAuto<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(name,0));
6715   if(name.empty())
6716     ret->setName("Mesh");
6717   ret->setCoords(da);
6718   mcIdType nbOfTuples(da->getNumberOfTuples());
6719   MCAuto<DataArrayIdType> c(DataArrayIdType::New()),cI(DataArrayIdType::New());
6720   c->alloc(2*nbOfTuples,1);
6721   cI->alloc(nbOfTuples+1,1);
6722   mcIdType *cp(c->getPointer()),*cip(cI->getPointer());
6723   *cip++=0;
6724   for(mcIdType i=0;i<nbOfTuples;i++)
6725     {
6726       *cp++=INTERP_KERNEL::NORM_POINT1;
6727       *cp++=i;
6728       *cip++=2*(i+1);
6729     }
6730   ret->setConnectivity(c,cI,true);
6731   return ret.retn();
6732 }
6733
6734 MCAuto<MEDCouplingUMesh> MEDCouplingUMesh::Build1DMeshFromCoords(DataArrayDouble *da)
6735 {
6736   if(!da)
6737     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build01MeshFromCoords : instance of DataArrayDouble must be not null !");
6738   da->checkAllocated();
6739   std::string name(da->getName());
6740   MCAuto<MEDCouplingUMesh> ret;
6741   {
6742     MCAuto<MEDCouplingCMesh> tmp(MEDCouplingCMesh::New());
6743     MCAuto<DataArrayDouble> arr(DataArrayDouble::New());
6744     arr->alloc(da->getNumberOfTuples());
6745     tmp->setCoordsAt(0,arr);
6746     ret=tmp->buildUnstructured();
6747   }
6748   ret->setCoords(da);
6749   if(name.empty())
6750     ret->setName("Mesh");
6751   else
6752     ret->setName(name);
6753   return ret;
6754 }
6755
6756 /*!
6757  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
6758  * Cells and nodes of
6759  * the first mesh precede cells and nodes of the second mesh within the result mesh.
6760  *  \param [in] mesh1 - the first mesh.
6761  *  \param [in] mesh2 - the second mesh.
6762  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6763  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6764  *          is no more needed.
6765  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
6766  *  \throw If the coordinates array is not set in none of the meshes.
6767  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
6768  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
6769  */
6770 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
6771 {
6772   std::vector<const MEDCouplingUMesh *> tmp(2);
6773   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
6774   return MergeUMeshes(tmp);
6775 }
6776
6777 /*!
6778  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
6779  * Cells and nodes of
6780  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
6781  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
6782  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6783  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6784  *          is no more needed.
6785  *  \throw If \a a.size() == 0.
6786  *  \throw If \a a[ *i* ] == NULL.
6787  *  \throw If the coordinates array is not set in none of the meshes.
6788  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
6789  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
6790  */
6791 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const std::vector<const MEDCouplingUMesh *>& a)
6792 {
6793   std::size_t sz=a.size();
6794   if(sz==0)
6795     return MergeUMeshesLL(a);
6796   for(std::size_t ii=0;ii<sz;ii++)
6797     if(!a[ii])
6798       {
6799         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
6800         throw INTERP_KERNEL::Exception(oss.str());
6801       }
6802   std::vector< MCAuto<MEDCouplingUMesh> > bb(sz);
6803   std::vector< const MEDCouplingUMesh * > aa(sz);
6804   int spaceDim=-3;
6805   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
6806     {
6807       const MEDCouplingUMesh *cur=a[i];
6808       const DataArrayDouble *coo=cur->getCoords();
6809       if(coo)
6810         spaceDim=int(coo->getNumberOfComponents());
6811     }
6812   if(spaceDim==-3)
6813     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
6814   for(std::size_t i=0;i<sz;i++)
6815     {
6816       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
6817       aa[i]=bb[i];
6818     }
6819   return MergeUMeshesLL(aa);
6820 }
6821
6822 /*!
6823  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
6824  * dimension and sharing the node coordinates array.
6825  * All cells of the first mesh precede all cells of the second mesh
6826  * within the result mesh.
6827  *  \param [in] mesh1 - the first mesh.
6828  *  \param [in] mesh2 - the second mesh.
6829  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6830  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6831  *          is no more needed.
6832  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
6833  *  \throw If the meshes do not share the node coordinates array.
6834  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
6835  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
6836  */
6837 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
6838 {
6839   std::vector<const MEDCouplingUMesh *> tmp(2);
6840   tmp[0]=mesh1; tmp[1]=mesh2;
6841   return MergeUMeshesOnSameCoords(tmp);
6842 }
6843
6844 /*!
6845  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
6846  * dimension and sharing the node coordinates array.
6847  * All cells of the *i*-th mesh precede all cells of the
6848  * (*i*+1)-th mesh within the result mesh.
6849  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
6850  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6851  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6852  *          is no more needed.
6853  *  \throw If \a a.size() == 0.
6854  *  \throw If \a a[ *i* ] == NULL.
6855  *  \throw If the meshes do not share the node coordinates array.
6856  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
6857  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
6858  */
6859 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
6860 {
6861   if(meshes.empty())
6862     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
6863   for(std::size_t ii=0;ii<meshes.size();ii++)
6864     if(!meshes[ii])
6865       {
6866         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
6867         throw INTERP_KERNEL::Exception(oss.str());
6868       }
6869   const DataArrayDouble *coords=meshes.front()->getCoords();
6870   int meshDim=meshes.front()->getMeshDimension();
6871   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
6872   mcIdType meshLgth=0;
6873   mcIdType meshIndexLgth=0;
6874   for(;iter!=meshes.end();iter++)
6875     {
6876       if(coords!=(*iter)->getCoords())
6877         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
6878       if(meshDim!=(*iter)->getMeshDimension())
6879         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
6880       meshLgth+=(*iter)->getNodalConnectivityArrayLen();
6881       meshIndexLgth+=(*iter)->getNumberOfCells();
6882     }
6883   MCAuto<DataArrayIdType> nodal=DataArrayIdType::New();
6884   nodal->alloc(meshLgth,1);
6885   mcIdType *nodalPtr=nodal->getPointer();
6886   MCAuto<DataArrayIdType> nodalIndex=DataArrayIdType::New();
6887   nodalIndex->alloc(meshIndexLgth+1,1);
6888   mcIdType *nodalIndexPtr=nodalIndex->getPointer();
6889   mcIdType offset=0;
6890   for(iter=meshes.begin();iter!=meshes.end();iter++)
6891     {
6892       const mcIdType *nod=(*iter)->getNodalConnectivity()->begin();
6893       const mcIdType *index=(*iter)->getNodalConnectivityIndex()->begin();
6894       mcIdType nbOfCells=(*iter)->getNumberOfCells();
6895       mcIdType meshLgth2=(*iter)->getNodalConnectivityArrayLen();
6896       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
6897       if(iter!=meshes.begin())
6898         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<mcIdType>(),offset));
6899       else
6900         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
6901       offset+=meshLgth2;
6902     }
6903   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
6904   ret->setName("merge");
6905   ret->setMeshDimension(meshDim);
6906   ret->setConnectivity(nodal,nodalIndex,true);
6907   ret->setCoords(coords);
6908   return ret;
6909 }
6910
6911 /*!
6912  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
6913  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
6914  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
6915  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
6916  * New" mode are returned for each input mesh.
6917  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
6918  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
6919  *          valid values [0,1,2], see zipConnectivityTraducer().
6920  *  \param [in,out] corr - an array of DataArrayIdType, of the same size as \a
6921  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
6922  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
6923  *          no more needed.
6924  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
6925  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
6926  *          is no more needed.
6927  *  \throw If \a meshes.size() == 0.
6928  *  \throw If \a meshes[ *i* ] == NULL.
6929  *  \throw If the meshes do not share the node coordinates array.
6930  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
6931  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
6932  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
6933  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
6934  */
6935 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayIdType *>& corr)
6936 {
6937   //All checks are delegated to MergeUMeshesOnSameCoords
6938   MCAuto<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
6939   MCAuto<DataArrayIdType> o2n=ret->zipConnectivityTraducer(compType);
6940   corr.resize(meshes.size());
6941   std::size_t nbOfMeshes=meshes.size();
6942   mcIdType offset=0;
6943   const mcIdType *o2nPtr=o2n->begin();
6944   for(std::size_t i=0;i<nbOfMeshes;i++)
6945     {
6946       DataArrayIdType *tmp=DataArrayIdType::New();
6947       mcIdType curNbOfCells=meshes[i]->getNumberOfCells();
6948       tmp->alloc(curNbOfCells,1);
6949       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
6950       offset+=curNbOfCells;
6951       tmp->setName(meshes[i]->getName());
6952       corr[i]=tmp;
6953     }
6954   return ret.retn();
6955 }
6956
6957 /*!
6958  * Makes all given meshes share the nodal connectivity array. The common connectivity
6959  * array is created by concatenating the connectivity arrays of all given meshes. All
6960  * the given meshes must be of the same space dimension but dimension of cells **can
6961  * differ**. This method is particularly useful in MEDLoader context to build a \ref
6962  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6963  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
6964  *  \param [in,out] meshes - a vector of meshes to update.
6965  *  \throw If any of \a meshes is NULL.
6966  *  \throw If the coordinates array is not set in any of \a meshes.
6967  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
6968  *  \throw If \a meshes are of different space dimension.
6969  */
6970 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
6971 {
6972   std::size_t sz=meshes.size();
6973   if(sz==0 || sz==1)
6974     return;
6975   std::vector< const DataArrayDouble * > coords(meshes.size());
6976   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
6977   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
6978     {
6979       if((*it))
6980         {
6981           (*it)->checkConnectivityFullyDefined();
6982           const DataArrayDouble *coo=(*it)->getCoords();
6983           if(coo)
6984             *it2=coo;
6985           else
6986             {
6987               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6988               oss << " has no coordinate array defined !";
6989               throw INTERP_KERNEL::Exception(oss.str());
6990             }
6991         }
6992       else
6993         {
6994           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6995           oss << " is null !";
6996           throw INTERP_KERNEL::Exception(oss.str());
6997         }
6998     }
6999   MCAuto<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7000   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7001   mcIdType offset=(*it)->getNumberOfNodes();
7002   (*it++)->setCoords(res);
7003   for(;it!=meshes.end();it++)
7004     {
7005       mcIdType oldNumberOfNodes=(*it)->getNumberOfNodes();
7006       (*it)->setCoords(res);
7007       (*it)->shiftNodeNumbersInConn(offset);
7008       offset+=oldNumberOfNodes;
7009     }
7010 }
7011
7012 /*!
7013  * Merges nodes coincident with a given precision within all given meshes that share
7014  * the nodal connectivity array. The given meshes **can be of different** mesh
7015  * dimension. This method is particularly useful in MEDLoader context to build a \ref
7016  * MEDCoupling::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7017  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7018  *  \param [in,out] meshes - a vector of meshes to update.
7019  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7020  *  \throw If any of \a meshes is NULL.
7021  *  \throw If the \a meshes do not share the same node coordinates array.
7022  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7023  */
7024 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7025 {
7026   if(meshes.empty())
7027     return ;
7028   std::set<const DataArrayDouble *> s;
7029   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7030     {
7031       if(*it)
7032         s.insert((*it)->getCoords());
7033       else
7034         {
7035           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 !";
7036           throw INTERP_KERNEL::Exception(oss.str());
7037         }
7038     }
7039   if(s.size()!=1)
7040     {
7041       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 !";
7042       throw INTERP_KERNEL::Exception(oss.str());
7043     }
7044   const DataArrayDouble *coo=*(s.begin());
7045   if(!coo)
7046     return;
7047   //
7048   DataArrayIdType *comm,*commI;
7049   coo->findCommonTuples(eps,-1,comm,commI);
7050   MCAuto<DataArrayIdType> tmp1(comm),tmp2(commI);
7051   mcIdType oldNbOfNodes=coo->getNumberOfTuples();
7052   mcIdType newNbOfNodes;
7053   MCAuto<DataArrayIdType> o2n=DataArrayIdType::ConvertIndexArrayToO2N(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7054   if(oldNbOfNodes==newNbOfNodes)
7055     return ;
7056   MCAuto<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->begin(),newNbOfNodes);
7057   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7058     {
7059       (*it)->renumberNodesInConn(o2n->begin());
7060       (*it)->setCoords(newCoords);
7061     }
7062 }
7063
7064
7065 /*!
7066  * This static operates only for coords in 3D. The polygon is specified by its connectivity nodes in [ \a begin , \a end ).
7067  */
7068 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const mcIdType *begin, const mcIdType *end, const double *coords)
7069 {
7070   std::size_t i, ip1;
7071   double v[3]={0.,0.,0.};
7072   std::size_t sz=std::distance(begin,end);
7073   if(!isQuadratic)
7074     for(i=0;i<sz;i++)
7075       {
7076         // Algorithm: sum in v the cross products of (e1, e2) where e_i it the vector between (0,0,0) and point i
7077         // and e2 is linear point directly following e1 in the connectivity. All points are used.
7078         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];
7079         v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7080         v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7081       }
7082   else
7083     {
7084       // Same algorithm as above but also using intermediate quadratic points.
7085       // (taking only linear points might lead to issues if the linearized version of the
7086       // polygon is not convex or self-intersecting ... see testCellOrientation4)
7087       std::size_t hsz = sz/2;
7088       for(std::size_t j=0;j<sz;j++)
7089         {
7090           if (j%2)  // current point i is quadratic, next point i+1 is standard
7091             {
7092               i = hsz+(j-1)/2;
7093               ip1 = ((j-1)/2 + 1)%hsz; // ip1 means "i+1", i.e. next point
7094             }
7095           else      // current point i is standard, next point i+1 is quadratic
7096             {
7097               i = j/2;
7098               ip1 = j/2+hsz;
7099             }
7100           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
7101           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
7102           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
7103         }
7104     }
7105   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
7106   return (ret>0.);
7107 }
7108
7109 /*!
7110  * The polyhedron is specified by its connectivity nodes in [ \a begin , \a end ).
7111  */
7112 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const mcIdType *begin, const mcIdType *end, const double *coords)
7113 {
7114   std::vector<std::pair<mcIdType,mcIdType> > edges;
7115   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7116   const mcIdType *bgFace=begin;
7117   for(std::size_t i=0;i<nbOfFaces;i++)
7118     {
7119       const mcIdType *endFace=std::find(bgFace+1,end,-1);
7120       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7121       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7122         {
7123           std::pair<mcIdType,mcIdType> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7124           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7125             return false;
7126           edges.push_back(p1);
7127         }
7128       bgFace=endFace+1;
7129     }
7130   return INTERP_KERNEL::calculateVolumeForPolyh2<mcIdType,INTERP_KERNEL::ALL_C_MODE>(begin,ToIdType(std::distance(begin,end)),coords)>-EPS_FOR_POLYH_ORIENTATION;
7131 }
7132
7133 /*!
7134  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7135  */
7136 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const mcIdType *begin, const mcIdType *end, const double *coords)
7137 {
7138   double vec0[3],vec1[3];
7139   std::size_t sz=std::distance(begin,end);
7140   if(sz%2!=0)
7141     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7142   mcIdType nbOfNodes=ToIdType(sz/2);
7143   INTERP_KERNEL::areaVectorOfPolygon<mcIdType,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7144   const double *pt0=coords+3*begin[0];
7145   const double *pt1=coords+3*begin[nbOfNodes];
7146   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7147   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7148 }
7149
7150 void MEDCouplingUMesh::CorrectExtrudedStaticCell(mcIdType *begin, mcIdType *end)
7151 {
7152   std::size_t sz=std::distance(begin,end);
7153   INTERP_KERNEL::AutoPtr<mcIdType> tmp=new mcIdType[sz];
7154   std::size_t nbOfNodes(sz/2);
7155   std::copy(begin,end,(mcIdType *)tmp);
7156   for(std::size_t j=1;j<nbOfNodes;j++)
7157     {
7158       begin[j]=tmp[nbOfNodes-j];
7159       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7160     }
7161 }
7162
7163 bool MEDCouplingUMesh::IsTetra4WellOriented(const mcIdType *begin, const mcIdType *end, const double *coords)
7164 {
7165   std::size_t sz=std::distance(begin,end);
7166   if(sz!=4)
7167     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkConsistency !");
7168   double vec0[3],vec1[3];
7169   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7170   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];
7171   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;
7172 }
7173
7174 bool MEDCouplingUMesh::IsPyra5WellOriented(const mcIdType *begin, const mcIdType *end, const double *coords)
7175 {
7176   std::size_t sz=std::distance(begin,end);
7177   if(sz!=5)
7178     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkConsistency !");
7179   double vec0[3];
7180   INTERP_KERNEL::areaVectorOfPolygon<mcIdType,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7181   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7182   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7183 }
7184
7185 /*!
7186  * 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 )
7187  * 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
7188  * a 2D space.
7189  *
7190  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7191  * \param [in] coords the coordinates with nb of components exactly equal to 3
7192  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7193  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7194  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7195  */
7196 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, mcIdType index, DataArrayIdType *res, MEDCouplingUMesh *faces,
7197                                               DataArrayIdType *E_Fi, DataArrayIdType *E_F, DataArrayIdType *F_Ei, DataArrayIdType *F_E)
7198 {
7199   mcIdType nbFaces = E_Fi->getIJ(index + 1, 0) - E_Fi->getIJ(index, 0);
7200   MCAuto<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7201   double *vPtr=v->getPointer();
7202   MCAuto<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,2);
7203   double *pPtr=p->getPointer();
7204   mcIdType *e_fi = E_Fi->getPointer(), *e_f = E_F->getPointer(), *f_ei = F_Ei->getPointer(), *f_e = F_E->getPointer();
7205   const mcIdType *f_idx = faces->getNodalConnectivityIndex()->getPointer(), *f_cnn = faces->getNodalConnectivity()->getPointer();
7206   for(mcIdType i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7207     {
7208       mcIdType face = e_f[e_fi[index] + i];
7209       ComputeVecAndPtOfFace(eps, coords->begin(), f_cnn + f_idx[face] + 1, f_cnn + f_idx[face + 1], vPtr, pPtr);
7210       // to differentiate faces going to different cells:
7211       pPtr++, *pPtr = 0;
7212       for (mcIdType j = f_ei[face]; j < f_ei[face + 1]; j++)
7213         *pPtr += FromIdType<double>(f_e[j]);
7214     }
7215   pPtr=p->getPointer(); vPtr=v->getPointer();
7216   DataArrayIdType *comm1=0,*commI1=0;
7217   v->findCommonTuples(eps,-1,comm1,commI1);
7218   for (mcIdType i = 0; i < nbFaces; i++)
7219     if (comm1->findIdFirstEqual(i) < 0)
7220       {
7221         comm1->pushBackSilent(i);
7222         commI1->pushBackSilent(comm1->getNumberOfTuples());
7223       }
7224   MCAuto<DataArrayIdType> comm1Auto(comm1),commI1Auto(commI1);
7225   const mcIdType *comm1Ptr=comm1->begin();
7226   const mcIdType *commI1Ptr=commI1->begin();
7227   mcIdType nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7228   res->pushBackSilent(ToIdType(INTERP_KERNEL::NORM_POLYHED));
7229   //
7230   for(mcIdType i=0;i<nbOfGrps1;i++)
7231     {
7232       mcIdType vecId=comm1Ptr[commI1Ptr[i]];
7233       MCAuto<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7234       DataArrayIdType *comm2=0,*commI2=0;
7235       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7236       for (mcIdType j = 0; j < commI1Ptr[i+1] - commI1Ptr[i]; j++)
7237         if (comm2->findIdFirstEqual(j) < 0)
7238           {
7239             comm2->pushBackSilent(j);
7240             commI2->pushBackSilent(comm2->getNumberOfTuples());
7241           }
7242       MCAuto<DataArrayIdType> comm2Auto(comm2),commI2Auto(commI2);
7243       const mcIdType *comm2Ptr=comm2->begin();
7244       const mcIdType *commI2Ptr=commI2->begin();
7245       mcIdType nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7246       for(mcIdType j=0;j<nbOfGrps2;j++)
7247         {
7248           if(commI2Ptr[j+1] == commI2Ptr[j] + 1)
7249             {
7250               mcIdType face = e_f[e_fi[index] + comm1Ptr[commI1Ptr[i] + comm2Ptr[commI2Ptr[j]]]]; //hmmm
7251               res->insertAtTheEnd(f_cnn + f_idx[face] + 1, f_cnn + f_idx[face + 1]);
7252               res->pushBackSilent(-1);
7253             }
7254           else
7255             {
7256               mcIdType pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7257               MCAuto<DataArrayIdType> ids2=comm2->selectByTupleIdSafeSlice(commI2Ptr[j],commI2Ptr[j+1],1);
7258               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7259               ids2->transformWithIndArr(e_f + e_fi[index], e_f + e_fi[index + 1]);
7260               MCAuto<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(faces->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7261               MCAuto<DataArrayIdType> idsNodeTmp=mm3->zipCoordsTraducer();
7262               MCAuto<DataArrayIdType> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7263               const mcIdType *idsNodePtr=idsNode->begin();
7264               double center[3]; center[0]=pPtr[2*pointId]*vPtr[3*vecId]; center[1]=pPtr[2*pointId]*vPtr[3*vecId+1]; center[2]=pPtr[2*pointId]*vPtr[3*vecId+2];
7265               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7266               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7267               if(std::abs(norm)>eps)
7268                 {
7269                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7270                   mm3->rotate(center,vec,angle);
7271                 }
7272               mm3->changeSpaceDimension(2);
7273               MCAuto<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7274               const mcIdType *conn4=mm4->getNodalConnectivity()->begin();
7275               const mcIdType *connI4=mm4->getNodalConnectivityIndex()->begin();
7276               mcIdType nbOfCells=mm4->getNumberOfCells();
7277               for(mcIdType k=0;k<nbOfCells;k++)
7278                 {
7279                   int l=0;
7280                   for(const mcIdType *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7281                     res->pushBackSilent(idsNodePtr[*work]);
7282                   res->pushBackSilent(-1);
7283                 }
7284             }
7285         }
7286     }
7287   res->popBackSilent();
7288 }
7289
7290 /*!
7291  * 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
7292  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7293  *
7294  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7295  * \param [in] coords coordinates expected to have 3 components.
7296  * \param [in] begin start of the nodal connectivity of the face.
7297  * \param [in] end end of the nodal connectivity (excluded) of the face.
7298  * \param [out] v the normalized vector of size 3
7299  * \param [out] p the pos of plane
7300  */
7301 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const mcIdType *begin, const mcIdType *end, double *v, double *p)
7302 {
7303   std::size_t nbPoints=std::distance(begin,end);
7304   if(nbPoints<3)
7305     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7306   double vec[3]={0.,0.,0.};
7307   std::size_t j=0;
7308   bool refFound=false;
7309   for(;j<nbPoints-1 && !refFound;j++)
7310     {
7311       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7312       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7313       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7314       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7315       if(norm>eps)
7316         {
7317           refFound=true;
7318           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7319         }
7320     }
7321   for(std::size_t i=j;i<nbPoints-1;i++)
7322     {
7323       double curVec[3];
7324       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7325       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7326       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7327       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7328       if(norm<eps)
7329         continue;
7330       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7331       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];
7332       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7333       if(norm>eps)
7334         {
7335           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7336           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7337           return ;
7338         }
7339     }
7340   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7341 }
7342
7343 /*!
7344  * This method tries to obtain a well oriented polyhedron.
7345  * If the algorithm fails, an exception will be thrown.
7346  */
7347 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(mcIdType *begin, mcIdType *end, const double *coords)
7348 {
7349   std::list< std::pair<mcIdType,mcIdType> > edgesOK,edgesFinished;
7350   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7351   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7352   isPerm[0]=true;
7353   mcIdType *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7354   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7355   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<mcIdType,mcIdType> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7356   //
7357   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7358     {
7359       bgFace=begin;
7360       std::size_t smthChanged=0;
7361       for(std::size_t i=0;i<nbOfFaces;i++)
7362         {
7363           endFace=std::find(bgFace+1,end,-1);
7364           nbOfEdgesInFace=std::distance(bgFace,endFace);
7365           if(!isPerm[i])
7366             {
7367               bool b;
7368               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7369                 {
7370                   std::pair<mcIdType,mcIdType> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7371                   std::pair<mcIdType,mcIdType> p2(p1.second,p1.first);
7372                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7373                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7374                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7375                 }
7376               if(isPerm[i])
7377                 {
7378                   if(!b)
7379                     std::reverse(bgFace+1,endFace);
7380                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7381                     {
7382                       std::pair<mcIdType,mcIdType> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7383                       std::pair<mcIdType,mcIdType> p2(p1.second,p1.first);
7384                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7385                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
7386                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7387                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str()); }
7388                       std::list< std::pair<mcIdType,mcIdType> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7389                       if(it!=edgesOK.end())
7390                         {
7391                           edgesOK.erase(it);
7392                           edgesFinished.push_back(p1);
7393                         }
7394                       else
7395                         edgesOK.push_back(p1);
7396                     }
7397                 }
7398             }
7399           bgFace=endFace+1;
7400         }
7401       if(smthChanged==0)
7402         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7403     }
7404   if(!edgesOK.empty())
7405     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7406   if(INTERP_KERNEL::calculateVolumeForPolyh2<mcIdType,INTERP_KERNEL::ALL_C_MODE>(begin,ToIdType(std::distance(begin,end)),coords)<-EPS_FOR_POLYH_ORIENTATION)
7407     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7408       bgFace=begin;
7409       for(std::size_t i=0;i<nbOfFaces;i++)
7410         {
7411           endFace=std::find(bgFace+1,end,-1);
7412           std::reverse(bgFace+1,endFace);
7413           bgFace=endFace+1;
7414         }
7415     }
7416 }
7417
7418
7419 /*!
7420  * This method makes the assumption spacedimension == meshdimension == 2.
7421  * This method works only for linear cells.
7422  *
7423  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7424  */
7425 DataArrayIdType *MEDCouplingUMesh::buildUnionOf2DMesh() const
7426 {
7427   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7428     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7429   MCAuto<MEDCouplingUMesh> skin(computeSkin());
7430   mcIdType oldNbOfNodes(skin->getNumberOfNodes());
7431   MCAuto<DataArrayIdType> o2n(skin->zipCoordsTraducer());
7432   mcIdType nbOfNodesExpected(skin->getNumberOfNodes());
7433   MCAuto<DataArrayIdType> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
7434   mcIdType nbCells=skin->getNumberOfCells();
7435   if(nbCells==nbOfNodesExpected)
7436     return buildUnionOf2DMeshLinear(skin,n2o);
7437   else if(2*nbCells==nbOfNodesExpected)
7438     return buildUnionOf2DMeshQuadratic(skin,n2o);
7439   else
7440     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
7441 }
7442
7443 /*!
7444  * This method makes the assumption spacedimension == meshdimension == 3.
7445  * This method works only for linear cells.
7446  *
7447  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7448  */
7449 DataArrayIdType *MEDCouplingUMesh::buildUnionOf3DMesh() const
7450 {
7451   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7452     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7453   MCAuto<MEDCouplingUMesh> m=computeSkin();
7454   const mcIdType *conn=m->getNodalConnectivity()->begin();
7455   const mcIdType *connI=m->getNodalConnectivityIndex()->begin();
7456   mcIdType nbOfCells=m->getNumberOfCells();
7457   MCAuto<DataArrayIdType> ret=DataArrayIdType::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7458   mcIdType *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
7459   if(nbOfCells<1)
7460     return ret.retn();
7461   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7462   for(mcIdType i=1;i<nbOfCells;i++)
7463     {
7464       *work++=-1;
7465       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7466     }
7467   return ret.retn();
7468 }
7469
7470 /*!
7471  * \brief Creates a graph of cell neighbors
7472  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
7473  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
7474  *  For example
7475  *  - index:  0 3 5 6 6
7476  *  - value:  1 2 3 2 3 3
7477  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
7478  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
7479  */
7480 MEDCouplingSkyLineArray* MEDCouplingUMesh::generateGraph() const
7481 {
7482   checkConnectivityFullyDefined();
7483
7484   int meshDim = this->getMeshDimension();
7485   MEDCoupling::DataArrayIdType* indexr=MEDCoupling::DataArrayIdType::New();
7486   MEDCoupling::DataArrayIdType* revConn=MEDCoupling::DataArrayIdType::New();
7487   this->getReverseNodalConnectivity(revConn,indexr);
7488   const mcIdType* indexr_ptr=indexr->begin();
7489   const mcIdType* revConn_ptr=revConn->begin();
7490
7491   const MEDCoupling::DataArrayIdType* index;
7492   const MEDCoupling::DataArrayIdType* conn;
7493   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
7494   index=this->getNodalConnectivityIndex();
7495   mcIdType nbCells=this->getNumberOfCells();
7496   const mcIdType* index_ptr=index->begin();
7497   const mcIdType* conn_ptr=conn->begin();
7498
7499   //creating graph arcs (cell to cell relations)
7500   //arcs are stored in terms of (index,value) notation
7501   // 0 3 5 6 6
7502   // 1 2 3 2 3 3
7503   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
7504   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
7505
7506   //warning here one node have less than or equal effective number of cell with it
7507   //but cell could have more than effective nodes
7508   //because other equals nodes in other domain (with other global inode)
7509   std::vector <mcIdType> cell2cell_index(nbCells+1,0);
7510   std::vector <mcIdType> cell2cell;
7511   cell2cell.reserve(3*nbCells);
7512
7513   for (mcIdType icell=0; icell<nbCells;icell++)
7514     {
7515       std::map<mcIdType,mcIdType > counter;
7516       for (mcIdType iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
7517         {
7518           mcIdType inode=conn_ptr[iconn];
7519           for (mcIdType iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
7520             {
7521               mcIdType icell2=revConn_ptr[iconnr];
7522               std::map<mcIdType,mcIdType>::iterator iter=counter.find(icell2);
7523               if (iter!=counter.end()) (iter->second)++;
7524               else counter.insert(std::make_pair(icell2,1));
7525             }
7526         }
7527       for (std::map<mcIdType,mcIdType>::const_iterator iter=counter.begin();
7528            iter!=counter.end(); iter++)
7529         if (iter->second >= meshDim)
7530           {
7531             cell2cell_index[icell+1]++;
7532             cell2cell.push_back(iter->first);
7533           }
7534     }
7535   indexr->decrRef();
7536   revConn->decrRef();
7537   cell2cell_index[0]=0;
7538   for (mcIdType icell=0; icell<nbCells;icell++)
7539     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
7540
7541   //filling up index and value to create skylinearray structure
7542   MEDCouplingSkyLineArray * array(MEDCouplingSkyLineArray::New(cell2cell_index,cell2cell));
7543   return array;
7544 }
7545
7546
7547 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
7548 {
7549   mcIdType nbOfCells=getNumberOfCells();
7550   if(nbOfCells<=0)
7551     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7552   ofs << "  <" << getVTKDataSetType() << ">\n";
7553   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7554   ofs << "      <PointData>\n" << pointData << std::endl;
7555   ofs << "      </PointData>\n";
7556   ofs << "      <CellData>\n" << cellData << std::endl;
7557   ofs << "      </CellData>\n";
7558   ofs << "      <Points>\n";
7559   if(getSpaceDimension()==3)
7560     _coords->writeVTK(ofs,8,"Points",byteData);
7561   else
7562     {
7563       MCAuto<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7564       coo->writeVTK(ofs,8,"Points",byteData);
7565     }
7566   ofs << "      </Points>\n";
7567   ofs << "      <Cells>\n";
7568   const mcIdType *cPtr=_nodal_connec->begin();
7569   const mcIdType *cIPtr=_nodal_connec_index->begin();
7570   MCAuto<DataArrayIdType> faceoffsets=DataArrayIdType::New(); faceoffsets->alloc(nbOfCells,1);
7571   MCAuto<DataArrayIdType> types=DataArrayIdType::New(); types->alloc(nbOfCells,1);
7572   MCAuto<DataArrayIdType> offsets=DataArrayIdType::New(); offsets->alloc(nbOfCells,1);
7573   MCAuto<DataArrayIdType> connectivity=DataArrayIdType::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
7574   mcIdType *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
7575   mcIdType szFaceOffsets=0,szConn=0;
7576   for(mcIdType i=0;i<nbOfCells;i++,w1++,w2++,w3++)
7577     {
7578       *w2=cPtr[cIPtr[i]];
7579       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
7580         {
7581           *w1=-1;
7582           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
7583           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
7584         }
7585       else
7586         {
7587           mcIdType deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
7588           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
7589           std::set<mcIdType> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
7590           *w3=szConn+ToIdType(c.size()); szConn+=ToIdType(c.size());
7591           w4=std::copy(c.begin(),c.end(),w4);
7592         }
7593     }
7594   std::unique_ptr<mcIdType[]> medcoupling2vtkTypeTraducer_mcIdType(new mcIdType[MEDCOUPLING2VTKTYPETRADUCER_LGTH]);
7595   for(auto ii = 0; ii<MEDCOUPLING2VTKTYPETRADUCER_LGTH ; ++ii)
7596     medcoupling2vtkTypeTraducer_mcIdType[ii] = MEDCOUPLING2VTKTYPETRADUCER[ii]!=MEDCOUPLING2VTKTYPETRADUCER_NONE?MEDCOUPLING2VTKTYPETRADUCER[ii] : -1;
7597   types->transformWithIndArr(medcoupling2vtkTypeTraducer_mcIdType.get(),medcoupling2vtkTypeTraducer_mcIdType.get()+MEDCOUPLING2VTKTYPETRADUCER_LGTH);
7598   types->writeVTK(ofs,8,"UInt8","types",byteData);
7599   std::string vtkTypeName = Traits<mcIdType>::VTKReprStr;
7600   offsets->writeVTK(ofs,8,vtkTypeName,"offsets",byteData);
7601   if(szFaceOffsets!=0)
7602     {//presence of Polyhedra
7603       connectivity->reAlloc(szConn);
7604       faceoffsets->writeVTK(ofs,8,vtkTypeName,"faceoffsets",byteData);
7605       MCAuto<DataArrayIdType> faces=DataArrayIdType::New(); faces->alloc(szFaceOffsets,1);
7606       w1=faces->getPointer();
7607       for(mcIdType i=0;i<nbOfCells;i++)
7608         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
7609           {
7610             mcIdType nbFaces=ToIdType(std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1))+1;
7611             *w1++=nbFaces;
7612             const mcIdType *w6=cPtr+cIPtr[i]+1,*w5=0;
7613             for(mcIdType j=0;j<nbFaces;j++)
7614               {
7615                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
7616                 *w1++=ToIdType(std::distance(w6,w5));
7617                 w1=std::copy(w6,w5,w1);
7618                 w6=w5+1;
7619               }
7620           }
7621       faces->writeVTK(ofs,8,vtkTypeName,"faces",byteData);
7622     }
7623   connectivity->writeVTK(ofs,8,vtkTypeName,"connectivity",byteData);
7624   ofs << "      </Cells>\n";
7625   ofs << "    </Piece>\n";
7626   ofs << "  </" << getVTKDataSetType() << ">\n";
7627 }
7628
7629 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
7630 {
7631   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
7632   if(_mesh_dim==-2)
7633     { stream << " Not set !"; return ; }
7634   stream << " Mesh dimension : " << _mesh_dim << ".";
7635   if(_mesh_dim==-1)
7636     return ;
7637   if(!_coords)
7638     { stream << " No coordinates set !"; return ; }
7639   if(!_coords->isAllocated())
7640     { stream << " Coordinates set but not allocated !"; return ; }
7641   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
7642   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
7643   if(!_nodal_connec_index)
7644     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
7645   if(!_nodal_connec_index->isAllocated())
7646     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
7647   mcIdType lgth=_nodal_connec_index->getNumberOfTuples();
7648   std::size_t cpt=_nodal_connec_index->getNumberOfComponents();
7649   if(cpt!=1 || lgth<1)
7650     return ;
7651   stream << std::endl << "Number of cells : " << lgth-1 << ".";
7652 }
7653
7654 std::string MEDCouplingUMesh::getVTKDataSetType() const
7655 {
7656   return std::string("UnstructuredGrid");
7657 }
7658
7659 std::string MEDCouplingUMesh::getVTKFileExtension() const
7660 {
7661   return std::string("vtu");
7662 }
7663
7664
7665
7666 /**
7667  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
7668  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
7669  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
7670  * The caller is to deal with the resulting DataArrayIdType.
7671  *  \throw If the coordinate array is not set.
7672  *  \throw If the nodal connectivity of the cells is not defined.
7673  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
7674  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
7675  *
7676  * \sa DataArrayIdType::sortEachPairToMakeALinkedList
7677  */
7678 DataArrayIdType *MEDCouplingUMesh::orderConsecutiveCells1D() const
7679 {
7680   checkFullyDefined();
7681   if(getMeshDimension()!=1)
7682     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
7683
7684   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
7685   MCAuto<DataArrayIdType> _d(DataArrayIdType::New()),_dI(DataArrayIdType::New());
7686   MCAuto<DataArrayIdType> _rD(DataArrayIdType::New()),_rDI(DataArrayIdType::New());
7687   MCAuto<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
7688   const mcIdType *d(_d->begin()), *dI(_dI->begin());
7689   const mcIdType *rD(_rD->begin()), *rDI(_rDI->begin());
7690   MCAuto<DataArrayIdType> _dsi(_rDI->deltaShiftIndex());
7691   const mcIdType * dsi(_dsi->begin());
7692   MCAuto<DataArrayIdType> dsii = _dsi->findIdsNotInRange(0,3);
7693   m_points=0;
7694   if (dsii->getNumberOfTuples())
7695     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
7696
7697   mcIdType nc=getNumberOfCells();
7698   MCAuto<DataArrayIdType> result(DataArrayIdType::New());
7699   result->alloc(nc,1);
7700
7701   // set of edges not used so far
7702   std::set<mcIdType> edgeSet;
7703   for (mcIdType i=0; i<nc; edgeSet.insert(i), i++);
7704
7705   mcIdType startSeg=0;
7706   mcIdType newIdx=0;
7707   // while we have points with only one neighbor segments
7708   do
7709     {
7710       std::list<mcIdType> linePiece;
7711       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
7712       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
7713         {
7714           // Fill the list forward (resp. backward) from the start segment:
7715           mcIdType activeSeg = startSeg;
7716           mcIdType prevPointId = -20;
7717           mcIdType ptId;
7718           while (!edgeSet.empty())
7719             {
7720               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
7721                 {
7722                   if (direction==0)
7723                     linePiece.push_back(activeSeg);
7724                   else
7725                     linePiece.push_front(activeSeg);
7726                   edgeSet.erase(activeSeg);
7727                 }
7728
7729               mcIdType ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
7730               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
7731               if (dsi[ptId] == 1) // hitting the end of the line
7732                 break;
7733               prevPointId = ptId;
7734               mcIdType seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
7735               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
7736             }
7737         }
7738       // Done, save final piece into DA:
7739       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
7740       newIdx += ToIdType(linePiece.size());
7741
7742       // identify next valid start segment (one which is not consumed)
7743       if(!edgeSet.empty())
7744         startSeg = *(edgeSet.begin());
7745     }
7746   while (!edgeSet.empty());
7747   return result.retn();
7748 }
7749
7750 /**
7751  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
7752  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
7753  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
7754  * a minimal creation of new nodes is wanted.
7755  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
7756  * nodes if a SEG3 is split without information of middle.
7757  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
7758  * avoid to have a non conform mesh.
7759  *
7760  * \return mcIdType - the number of new nodes created (in most of cases 0).
7761  *
7762  * \throw If \a this is not coherent.
7763  * \throw If \a this has not spaceDim equal to 2.
7764  * \throw If \a this has not meshDim equal to 2.
7765  * \throw If some subcells needed to be split are orphan.
7766  * \sa MEDCouplingUMesh::conformize2D
7767  */
7768 mcIdType MEDCouplingUMesh::split2DCells(const DataArrayIdType *desc, const DataArrayIdType *descI, const DataArrayIdType *subNodesInSeg, const DataArrayIdType *subNodesInSegI, const DataArrayIdType *midOpt, const DataArrayIdType *midOptI)
7769 {
7770   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
7771     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
7772   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
7773   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
7774     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
7775   if(midOpt==0 && midOptI==0)
7776     {
7777       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
7778       return 0;
7779     }
7780   else if(midOpt!=0 && midOptI!=0)
7781     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
7782   else
7783     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
7784 }
7785
7786 /*!
7787  * 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
7788  * 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
7789  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
7790  * 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
7791  * 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.
7792  *
7793  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
7794  */
7795 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const mcIdType *nodalConnBg, const mcIdType *nodalConnEnd, DataArrayIdType *nodalConnecOut)
7796 {
7797   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
7798   if(sz>=4)
7799     {
7800       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
7801       if(cm.getDimension()==2)
7802         {
7803           const mcIdType *node=nodalConnBg+1;
7804           mcIdType startNode=*node++;
7805           double refX=coords[2*startNode];
7806           for(;node!=nodalConnEnd;node++)
7807             {
7808               if(coords[2*(*node)]<refX)
7809                 {
7810                   startNode=*node;
7811                   refX=coords[2*startNode];
7812                 }
7813             }
7814           std::vector<mcIdType> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
7815           refX=1e300;
7816           double tmp1;
7817           double tmp2[2];
7818           double angle0=-M_PI/2;
7819           //
7820           mcIdType nextNode=-1;
7821           mcIdType prevNode=-1;
7822           double resRef;
7823           double angleNext=0.;
7824           while(nextNode!=startNode)
7825             {
7826               nextNode=-1;
7827               resRef=1e300;
7828               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
7829                 {
7830                   if(*node!=tmpOut.back() && *node!=prevNode)
7831                     {
7832                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
7833                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
7834                       double res;
7835                       if(angleM<=angle0)
7836                         res=angle0-angleM;
7837                       else
7838                         res=angle0-angleM+2.*M_PI;
7839                       if(res<resRef)
7840                         {
7841                           nextNode=*node;
7842                           resRef=res;
7843                           angleNext=angleM;
7844                         }
7845                     }
7846                 }
7847               if(nextNode!=startNode)
7848                 {
7849                   angle0=angleNext-M_PI;
7850                   if(angle0<-M_PI)
7851                     angle0+=2*M_PI;
7852                   prevNode=tmpOut.back();
7853                   tmpOut.push_back(nextNode);
7854                 }
7855             }
7856           std::vector<mcIdType> tmp3(2*(sz-1));
7857           std::vector<mcIdType>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
7858           std::copy(nodalConnBg+1,nodalConnEnd,it);
7859           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
7860             {
7861               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7862               return false;
7863             }
7864           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
7865             {
7866               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7867               return false;
7868             }
7869           else
7870             {
7871               nodalConnecOut->pushBackSilent(ToIdType(INTERP_KERNEL::NORM_POLYGON));
7872               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
7873               return true;
7874             }
7875         }
7876       else
7877         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7878     }
7879   else
7880     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7881 }
7882
7883 /*!
7884  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
7885  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
7886  * This method start from id 0 that will be contained in output DataArrayIdType. It searches then all neighbors of id0 looking at arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
7887  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
7888  * A negative value in \b arrIn means that it is ignored.
7889  * 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.
7890  *
7891  * \param [in] arrIn arr origin array from which the extraction will be done.
7892  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7893  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
7894  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
7895  */
7896 DataArrayIdType *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayIdType *arrIn, const DataArrayIdType *arrIndxIn)
7897 {
7898   mcIdType seed=0,nbOfDepthPeelingPerformed=0;
7899   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
7900 }
7901
7902 /*!
7903  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
7904  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
7905  * This method start from id 0 that will be contained in output DataArrayIdType. It searches then all neighbors of id0 regarding arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
7906  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
7907  * A negative value in \b arrIn means that it is ignored.
7908  * 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.
7909  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
7910  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
7911  * \param [in] arrIn arr origin array from which the extraction will be done.
7912  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
7913  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
7914  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
7915  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
7916  * \sa MEDCouplingUMesh::partitionBySpreadZone
7917  */
7918 DataArrayIdType *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const mcIdType *seedBg, const mcIdType *seedEnd, const DataArrayIdType *arrIn, const DataArrayIdType *arrIndxIn, mcIdType nbOfDepthPeeling, mcIdType& nbOfDepthPeelingPerformed)
7919 {
7920   nbOfDepthPeelingPerformed=0;
7921   if(!arrIndxIn)
7922     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
7923   mcIdType nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
7924   if(nbOfTuples<=0)
7925     {
7926       DataArrayIdType *ret=DataArrayIdType::New(); ret->alloc(0,1);
7927       return ret;
7928     }
7929   //
7930   std::vector<bool> fetched(nbOfTuples,false);
7931   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
7932 }
7933
7934
7935
7936 /*!
7937  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
7938  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
7939  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
7940  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
7941  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
7942  *
7943  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
7944  */
7945 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
7946 {
7947   checkFullyDefined();
7948   int mdim=getMeshDimension();
7949   int spaceDim=getSpaceDimension();
7950   if(mdim!=spaceDim)
7951     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
7952   std::vector<DataArrayIdType *> partition=partitionBySpreadZone();
7953   std::vector< MCAuto<DataArrayIdType> > partitionAuto; partitionAuto.reserve(partition.size());
7954   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MCAuto<DataArrayIdType> > >(partitionAuto));
7955   MCAuto<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
7956   ret->setCoords(getCoords());
7957   ret->allocateCells(ToIdType(partition.size()));
7958   //
7959   for(std::vector<DataArrayIdType *>::const_iterator it=partition.begin();it!=partition.end();it++)
7960     {
7961       MCAuto<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
7962       MCAuto<DataArrayIdType> cell;
7963       switch(mdim)
7964       {
7965         case 2:
7966           cell=tmp->buildUnionOf2DMesh();
7967           break;
7968         case 3:
7969           cell=tmp->buildUnionOf3DMesh();
7970           break;
7971         default:
7972           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
7973       }
7974
7975       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->begin()+1);
7976     }
7977   //
7978   ret->finishInsertingCells();
7979   return ret.retn();
7980 }
7981
7982 /*!
7983  * This method partitions \b this into contiguous zone.
7984  * This method only needs a well defined connectivity. Coordinates are not considered here.
7985  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
7986  */
7987 std::vector<DataArrayIdType *> MEDCouplingUMesh::partitionBySpreadZone() const
7988 {
7989   DataArrayIdType *neigh=0,*neighI=0;
7990   computeNeighborsOfCells(neigh,neighI);
7991   MCAuto<DataArrayIdType> neighAuto(neigh),neighIAuto(neighI);
7992   return PartitionBySpreadZone(neighAuto,neighIAuto);
7993 }
7994
7995 std::vector<DataArrayIdType *> MEDCouplingUMesh::PartitionBySpreadZone(const DataArrayIdType *arrIn, const DataArrayIdType *arrIndxIn)
7996 {
7997   if(!arrIn || !arrIndxIn)
7998     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : null input pointers !");
7999   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8000   mcIdType nbOfTuples(arrIndxIn->getNumberOfTuples());
8001   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1 || nbOfTuples<1)
8002     throw INTERP_KERNEL::Exception("PartitionBySpreadZone : invalid arrays in input !");
8003   mcIdType nbOfCellsCur(nbOfTuples-1);
8004   std::vector<DataArrayIdType *> ret;
8005   if(nbOfCellsCur<=0)
8006     return ret;
8007   std::vector<bool> fetchedCells(nbOfCellsCur,false);
8008   std::vector< MCAuto<DataArrayIdType> > ret2;
8009   mcIdType seed=0;
8010   while(seed<nbOfCellsCur)
8011     {
8012       mcIdType nbOfPeelPerformed=0;
8013       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfPeelPerformed));
8014       seed=ToIdType(std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false)));
8015     }
8016   for(std::vector< MCAuto<DataArrayIdType> >::iterator it=ret2.begin();it!=ret2.end();it++)
8017     ret.push_back((*it).retn());
8018   return ret;
8019 }
8020
8021 /*!
8022  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
8023  * newly allocated DataArrayIdType instance with 2 components ready to be interpreted as input of DataArrayIdType::findRangeIdForEachTuple method.
8024  *
8025  * \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.
8026  * \return a newly allocated DataArrayIdType to be managed by the caller.
8027  * \throw In case of \a code has not the right format (typically of size 3*n)
8028  */
8029 DataArrayIdType *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<mcIdType>& code)
8030 {
8031   MCAuto<DataArrayIdType> ret=DataArrayIdType::New();
8032   std::size_t nb=code.size()/3;
8033   if(code.size()%3!=0)
8034     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
8035   ret->alloc(nb,2);
8036   mcIdType *retPtr=ret->getPointer();
8037   for(std::size_t i=0;i<nb;i++,retPtr+=2)
8038     {
8039       retPtr[0]=code[3*i+2];
8040       retPtr[1]=code[3*i+2]+code[3*i+1];
8041     }
8042   return ret.retn();
8043 }
8044
8045 /*!
8046  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
8047  * All cells in \a this are expected to be linear 3D cells.
8048  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
8049  * It leads to an increase to number of cells.
8050  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
8051  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
8052  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
8053  *
8054  * \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.
8055  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
8056  * \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.
8057  * \param [out] n2oCells - A new instance of DataArrayIdType holding, for each new cell,
8058  *          an id of old cell producing it. The caller is to delete this array using
8059  *         decrRef() as it is no more needed.
8060  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
8061  *
8062  * \warning This method operates on each cells in this independently ! So it can leads to non conform mesh in returned value ! If you expect to have a conform mesh in output
8063  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
8064  *
8065  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
8066  * \throw If \a this is not fully constituted with linear 3D cells.
8067  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
8068  */
8069 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayIdType *& n2oCells, mcIdType& nbOfAdditionalPoints) const
8070 {
8071   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
8072   checkConnectivityFullyDefined();
8073   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8074     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
8075   mcIdType nbOfCells=getNumberOfCells();
8076   mcIdType nbNodes(getNumberOfNodes());
8077   MCAuto<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
8078   MCAuto<DataArrayIdType> ret(DataArrayIdType::New()); ret->alloc(nbOfCells,1);
8079   mcIdType *retPt(ret->getPointer());
8080   MCAuto<DataArrayIdType> newConn(DataArrayIdType::New()); newConn->alloc(0,1);
8081   MCAuto<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
8082   const mcIdType *oldc(_nodal_connec->begin());
8083   const mcIdType *oldci(_nodal_connec_index->begin());
8084   const double *coords(_coords->begin());
8085   for(mcIdType i=0;i<nbOfCells;i++,oldci++,retPt++)
8086     {
8087       std::vector<mcIdType> a; std::vector<double> b;
8088       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
8089       std::size_t nbOfTet(a.size()/4); *retPt=ToIdType(nbOfTet);
8090       const mcIdType *aa(&a[0]);
8091       if(!b.empty())
8092         {
8093           for(std::vector<mcIdType>::iterator it=a.begin();it!=a.end();it++)
8094             if(*it<0)
8095               *it=(-(*(it))-1+nbNodes);
8096           addPts->insertAtTheEnd(b.begin(),b.end());
8097           nbNodes+=ToIdType(b.size()/3);
8098         }
8099       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
8100         newConn->insertAtTheEnd(aa,aa+4);
8101     }
8102   if(!addPts->empty())
8103     {
8104       addPts->rearrange(3);
8105       nbOfAdditionalPoints=addPts->getNumberOfTuples();
8106       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
8107       ret0->setCoords(addPts);
8108     }
8109   else
8110     {
8111       nbOfAdditionalPoints=0;
8112       ret0->setCoords(getCoords());
8113     }
8114   ret0->setNodalConnectivity(newConn);
8115   //
8116   ret->computeOffsetsFull();
8117   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
8118   return ret0.retn();
8119 }
8120
8121 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
8122     _own_cell(true),_cell_id(-1),_nb_cell(0)
8123 {
8124   if(mesh)
8125     {
8126       mesh->incrRef();
8127       _nb_cell=mesh->getNumberOfCells();
8128     }
8129 }
8130
8131 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
8132 {
8133   if(_mesh)
8134     _mesh->decrRef();
8135   if(_own_cell)
8136     delete _cell;
8137 }
8138
8139 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, mcIdType bg, mcIdType end):_mesh(mesh),_cell(itc),
8140     _own_cell(false),_cell_id(bg-1),
8141     _nb_cell(end)
8142 {
8143   if(mesh)
8144     mesh->incrRef();
8145 }
8146
8147 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
8148 {
8149   _cell_id++;
8150   if(_cell_id<_nb_cell)
8151     {
8152       _cell->next();
8153       return _cell;
8154     }
8155   else
8156     return 0;
8157 }
8158
8159 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
8160 {
8161   if(_mesh)
8162     _mesh->incrRef();
8163 }
8164
8165 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
8166 {
8167   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
8168 }
8169
8170 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
8171 {
8172   if(_mesh)
8173     _mesh->decrRef();
8174 }
8175
8176 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, mcIdType bg, mcIdType end):_mesh(mesh),_type(type),
8177     _itc(itc),
8178     _bg(bg),_end(end)
8179 {
8180   if(_mesh)
8181     _mesh->incrRef();
8182 }
8183
8184 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
8185 {
8186   if(_mesh)
8187     _mesh->decrRef();
8188 }
8189
8190 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
8191 {
8192   return _type;
8193 }
8194
8195 mcIdType MEDCouplingUMeshCellEntry::getNumberOfElems() const
8196 {
8197   return _end-_bg;
8198 }
8199
8200 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
8201 {
8202   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
8203 }
8204
8205 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
8206 {
8207   if(mesh)
8208     {
8209       mesh->incrRef();
8210       _nb_cell=mesh->getNumberOfCells();
8211     }
8212 }
8213
8214 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
8215 {
8216   if(_mesh)
8217     _mesh->decrRef();
8218   delete _cell;
8219 }
8220
8221 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
8222 {
8223   const mcIdType *c=_mesh->getNodalConnectivity()->begin();
8224   const mcIdType *ci=_mesh->getNodalConnectivityIndex()->begin();
8225   if(_cell_id<_nb_cell)
8226     {
8227       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
8228       mcIdType nbOfElems=ToIdType(std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,MEDCouplingImpl::ConnReader(c,type))));
8229       mcIdType startId=_cell_id;
8230       _cell_id+=nbOfElems;
8231       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
8232     }
8233   else
8234     return 0;
8235 }
8236
8237 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
8238 {
8239   if(mesh)
8240     {
8241       _conn=mesh->getNodalConnectivity()->getPointer();
8242       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
8243     }
8244 }
8245
8246 void MEDCouplingUMeshCell::next()
8247 {
8248   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8249     {
8250       _conn+=_conn_lgth;
8251       _conn_indx++;
8252     }
8253   _conn_lgth=_conn_indx[1]-_conn_indx[0];
8254 }
8255
8256 std::string MEDCouplingUMeshCell::repr() const
8257 {
8258   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8259     {
8260       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
8261       oss << " : ";
8262       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<mcIdType>(oss," "));
8263       return oss.str();
8264     }
8265   else
8266     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
8267 }
8268
8269 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
8270 {
8271   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8272     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
8273   else
8274     return INTERP_KERNEL::NORM_ERROR;
8275 }
8276
8277 const mcIdType *MEDCouplingUMeshCell::getAllConn(mcIdType& lgth) const
8278 {
8279   lgth=_conn_lgth;
8280   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8281     return _conn;
8282   else
8283     return 0;
8284 }