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