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