Salome HOME
Fixing various C++ covariances mismatches in the API
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "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
45 #include <sstream>
46 #include <fstream>
47 #include <numeric>
48 #include <cstring>
49 #include <limits>
50 #include <list>
51
52 using namespace ParaMEDMEM;
53
54 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
55
56 /// @cond INTERNAL
57 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
58 /// @endcond
59
60 MEDCouplingUMesh *MEDCouplingUMesh::New()
61 {
62   return new MEDCouplingUMesh;
63 }
64
65 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
66 {
67   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
68   ret->setName(meshName);
69   ret->setMeshDimension(meshDim);
70   return ret;
71 }
72
73 /*!
74  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
75  * between \a this and the new mesh.
76  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
77  *          delete this mesh using decrRef() as it is no more needed. 
78  */
79 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
80 {
81   return clone(true);
82 }
83
84 /*!
85  * Returns a new MEDCouplingMesh which is a copy of \a this one.
86  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
87  * this mesh are shared by the new mesh.
88  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
89  *          delete this mesh using decrRef() as it is no more needed. 
90  */
91 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
92 {
93   return new MEDCouplingUMesh(*this,recDeepCpy);
94 }
95
96 /*!
97  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
98  * The coordinates are shared between \a this and the returned instance.
99  * 
100  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
101  * \sa MEDCouplingUMesh::deepCpy
102  */
103 MEDCouplingUMesh *MEDCouplingUMesh::deepCpyConnectivityOnly() const
104 {
105   checkConnectivityFullyDefined();
106   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
107   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
108   ret->setConnectivity(c,ci);
109   return ret.retn();
110 }
111
112 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
113 {
114   if(!other)
115     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
116   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
117   if(!otherC)
118     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
119   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
120   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
121 }
122
123 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
124 {
125   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
126   return ret;
127 }
128
129 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
130 {
131   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
132   ret.push_back(_nodal_connec);
133   ret.push_back(_nodal_connec_index);
134   return ret;
135 }
136
137 void MEDCouplingUMesh::updateTime() const
138 {
139   MEDCouplingPointSet::updateTime();
140   if(_nodal_connec)
141     {
142       updateTimeWith(*_nodal_connec);
143     }
144   if(_nodal_connec_index)
145     {
146       updateTimeWith(*_nodal_connec_index);
147     }
148 }
149
150 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
151 {
152 }
153
154 /*!
155  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
156  * then \a this mesh is most probably is writable, exchangeable and available for most
157  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
158  * this method to check that all is in order with \a this mesh.
159  *  \throw If the mesh dimension is not set.
160  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
161  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
162  *  \throw If the connectivity data array has more than one component.
163  *  \throw If the connectivity data array has a named component.
164  *  \throw If the connectivity index data array has more than one component.
165  *  \throw If the connectivity index data array has a named component.
166  */
167 void MEDCouplingUMesh::checkCoherency() const
168 {
169   if(_mesh_dim<-1)
170     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
171   if(_mesh_dim!=-1)
172     MEDCouplingPointSet::checkCoherency();
173   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
174     {
175       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
176         {
177           std::ostringstream message;
178           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
179           throw INTERP_KERNEL::Exception(message.str().c_str());
180         }
181     }
182   if(_nodal_connec)
183     {
184       if(_nodal_connec->getNumberOfComponents()!=1)
185         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
186       if(_nodal_connec->getInfoOnComponent(0)!="")
187         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
188     }
189   else
190     if(_mesh_dim!=-1)
191       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
192   if(_nodal_connec_index)
193     {
194       if(_nodal_connec_index->getNumberOfComponents()!=1)
195         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
196       if(_nodal_connec_index->getInfoOnComponent(0)!="")
197         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
198     }
199   else
200     if(_mesh_dim!=-1)
201       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
202 }
203
204 /*!
205  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
206  * then \a this mesh is most probably is writable, exchangeable and available for all
207  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
208  * method thoroughly checks the nodal connectivity.
209  *  \param [in] eps - a not used parameter.
210  *  \throw If the mesh dimension is not set.
211  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
212  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
213  *  \throw If the connectivity data array has more than one component.
214  *  \throw If the connectivity data array has a named component.
215  *  \throw If the connectivity index data array has more than one component.
216  *  \throw If the connectivity index data array has a named component.
217  *  \throw If number of nodes defining an element does not correspond to the type of element.
218  *  \throw If the nodal connectivity includes an invalid node id.
219  */
220 void MEDCouplingUMesh::checkCoherency1(double eps) const
221 {
222   checkCoherency();
223   if(_mesh_dim==-1)
224     return ;
225   int meshDim=getMeshDimension();
226   int nbOfNodes=getNumberOfNodes();
227   int nbOfCells=getNumberOfCells();
228   const int *ptr=_nodal_connec->getConstPointer();
229   const int *ptrI=_nodal_connec_index->getConstPointer();
230   for(int i=0;i<nbOfCells;i++)
231     {
232       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
233       if((int)cm.getDimension()!=meshDim)
234         {
235           std::ostringstream oss;
236           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
237           throw INTERP_KERNEL::Exception(oss.str().c_str());
238         }
239       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
240       if(!cm.isDynamic())
241         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
242           {
243             std::ostringstream oss;
244             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
245             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
246             throw INTERP_KERNEL::Exception(oss.str().c_str());
247           }
248       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
249         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
250           {
251             std::ostringstream oss;
252             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
253             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
254             throw INTERP_KERNEL::Exception(oss.str().c_str());
255           }
256       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
257         {
258           int nodeId=*w;
259           if(nodeId>=0)
260             {
261               if(nodeId>=nbOfNodes)
262                 {
263                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
264                   throw INTERP_KERNEL::Exception(oss.str().c_str());
265                 }
266             }
267           else if(nodeId<-1)
268             {
269               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
270               throw INTERP_KERNEL::Exception(oss.str().c_str());
271             }
272           else
273             {
274               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
275                 {
276                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
277                   throw INTERP_KERNEL::Exception(oss.str().c_str());
278                 }
279             }
280         }
281     }
282 }
283
284
285 /*!
286  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
287  * then \a this mesh is most probably is writable, exchangeable and available for all
288  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
289  *  \param [in] eps - a not used parameter.
290  *  \throw If the mesh dimension is not set.
291  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
292  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
293  *  \throw If the connectivity data array has more than one component.
294  *  \throw If the connectivity data array has a named component.
295  *  \throw If the connectivity index data array has more than one component.
296  *  \throw If the connectivity index data array has a named component.
297  *  \throw If number of nodes defining an element does not correspond to the type of element.
298  *  \throw If the nodal connectivity includes an invalid node id.
299  */
300 void MEDCouplingUMesh::checkCoherency2(double eps) const
301 {
302   checkCoherency1(eps);
303 }
304
305 /*!
306  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
307  * elements contained in the mesh. For more info on the mesh dimension see
308  * \ref MEDCouplingUMeshPage.
309  *  \param [in] meshDim - a new mesh dimension.
310  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
311  */
312 void MEDCouplingUMesh::setMeshDimension(int meshDim)
313 {
314   if(meshDim<-1 || meshDim>3)
315     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
316   _mesh_dim=meshDim;
317   declareAsNew();
318 }
319
320 /*!
321  * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
322  * the less will the library need to reallocate memory. If the number of cells to be inserted is not known simply put 0 to this parameter.
323  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
324  *
325  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
326  *
327  *  \if ENABLE_EXAMPLES
328  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
329  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
330  *  \endif
331  */
332 void MEDCouplingUMesh::allocateCells(int nbOfCells)
333 {
334   if(nbOfCells<0)
335     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
336   if(_nodal_connec_index)
337     {
338       _nodal_connec_index->decrRef();
339     }
340   if(_nodal_connec)
341     {
342       _nodal_connec->decrRef();
343     }
344   _nodal_connec_index=DataArrayInt::New();
345   _nodal_connec_index->reserve(nbOfCells+1);
346   _nodal_connec_index->pushBackSilent(0);
347   _nodal_connec=DataArrayInt::New();
348   _nodal_connec->reserve(2*nbOfCells);
349   _types.clear();
350   declareAsNew();
351 }
352
353 /*!
354  * Appends a cell to the connectivity array. For deeper understanding what is
355  * happening see \ref MEDCouplingUMeshNodalConnectivity.
356  *  \param [in] type - type of cell to add.
357  *  \param [in] size - number of nodes constituting this cell.
358  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
359  * 
360  *  \if ENABLE_EXAMPLES
361  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
362  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
363  *  \endif
364  */
365 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
366 {
367   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
368   if(_nodal_connec_index==0)
369     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
370   if((int)cm.getDimension()==_mesh_dim)
371     {
372       if(!cm.isDynamic())
373         if(size!=(int)cm.getNumberOfNodes())
374           {
375             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
376             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
377             throw INTERP_KERNEL::Exception(oss.str().c_str());
378           }
379       int idx=_nodal_connec_index->back();
380       int val=idx+size+1;
381       _nodal_connec_index->pushBackSilent(val);
382       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
383       _types.insert(type);
384     }
385   else
386     {
387       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
388       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
389       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
390       throw INTERP_KERNEL::Exception(oss.str().c_str());
391     }
392 }
393
394 /*!
395  * Compacts data arrays to release unused memory. This method is to be called after
396  * finishing cell insertion using \a this->insertNextCell().
397  * 
398  *  \if ENABLE_EXAMPLES
399  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
400  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
401  *  \endif
402  */
403 void MEDCouplingUMesh::finishInsertingCells()
404 {
405   _nodal_connec->pack();
406   _nodal_connec_index->pack();
407   _nodal_connec->declareAsNew();
408   _nodal_connec_index->declareAsNew();
409   updateTime();
410 }
411
412 /*!
413  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
414  * Useful for python users.
415  */
416 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
417 {
418   return new MEDCouplingUMeshCellIterator(this);
419 }
420
421 /*!
422  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
423  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
424  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
425  * Useful for python users.
426  */
427 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
428 {
429   if(!checkConsecutiveCellTypes())
430     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
431   return new MEDCouplingUMeshCellByTypeEntry(this);
432 }
433
434 /*!
435  * Returns a set of all cell types available in \a this mesh.
436  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
437  * \warning this method does not throw any exception even if \a this is not defined.
438  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
439  */
440 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
441 {
442   return _types;
443 }
444
445 /*!
446  * This method returns the sorted list of geometric types in \a this.
447  * 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
448  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
449  *
450  * \throw if connectivity in \a this is not correctly defined.
451  *  
452  * \sa MEDCouplingMesh::getAllGeoTypes
453  */
454 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
455 {
456   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
457   checkConnectivityFullyDefined();
458   int nbOfCells(getNumberOfCells());
459   if(nbOfCells==0)
460     return ret;
461   if(getMeshLength()<1)
462     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
463   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
464   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
465   for(int i=1;i<nbOfCells;i++,ci++)
466     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
467       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
468   return ret;
469 }
470
471 /*!
472  * This method is a method that compares \a this and \a other.
473  * This method compares \b all attributes, even names and component names.
474  */
475 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
476 {
477   if(!other)
478     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
479   std::ostringstream oss; oss.precision(15);
480   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
481   if(!otherC)
482     {
483       reason="mesh given in input is not castable in MEDCouplingUMesh !";
484       return false;
485     }
486   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
487     return false;
488   if(_mesh_dim!=otherC->_mesh_dim)
489     {
490       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
491       reason=oss.str();
492       return false;
493     }
494   if(_types!=otherC->_types)
495     {
496       oss << "umesh geometric type mismatch :\nThis geometric types are :";
497       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
498         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
499       oss << "\nOther geometric types are :";
500       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
501         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
502       reason=oss.str();
503       return false;
504     }
505   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
506     if(_nodal_connec==0 || otherC->_nodal_connec==0)
507       {
508         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
509         return false;
510       }
511   if(_nodal_connec!=otherC->_nodal_connec)
512     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
513       {
514         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
515         return false;
516       }
517   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
518     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
519       {
520         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
521         return false;
522       }
523   if(_nodal_connec_index!=otherC->_nodal_connec_index)
524     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
525       {
526         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
527         return false;
528       }
529   return true;
530 }
531
532 /*!
533  * Checks if data arrays of this mesh (node coordinates, nodal
534  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
535  * not considered.
536  *  \param [in] other - the mesh to compare with.
537  *  \param [in] prec - precision value used to compare node coordinates.
538  *  \return bool - \a true if the two meshes are same.
539  */
540 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
541 {
542   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
543   if(!otherC)
544     return false;
545   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
546     return false;
547   if(_mesh_dim!=otherC->_mesh_dim)
548     return false;
549   if(_types!=otherC->_types)
550     return false;
551   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
552     if(_nodal_connec==0 || otherC->_nodal_connec==0)
553       return false;
554   if(_nodal_connec!=otherC->_nodal_connec)
555     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
556       return false;
557   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
558     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
559       return false;
560   if(_nodal_connec_index!=otherC->_nodal_connec_index)
561     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
562       return false;
563   return true;
564 }
565
566 /*!
567  * Checks if \a this and \a other meshes are geometrically equivalent with high
568  * probability, else an exception is thrown. The meshes are considered equivalent if
569  * (1) meshes contain the same number of nodes and the same number of elements of the
570  * same types (2) three cells of the two meshes (first, last and middle) are based
571  * on coincident nodes (with a specified precision).
572  *  \param [in] other - the mesh to compare with.
573  *  \param [in] prec - the precision used to compare nodes of the two meshes.
574  *  \throw If the two meshes do not match.
575  */
576 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
577 {
578   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
579   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
580   if(!otherC)
581     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
582 }
583
584 /*!
585  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
586  * cells each node belongs to.
587  * \warning For speed reasons, this method does not check if node ids in the nodal
588  *          connectivity correspond to the size of node coordinates array.
589  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
590  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
591  *        dividing cell ids in \a revNodal into groups each referring to one
592  *        node. Its every element (except the last one) is an index pointing to the
593  *         first id of a group of cells. For example cells sharing the node #1 are 
594  *        described by following range of indices: 
595  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
596  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
597  *        Number of cells sharing the *i*-th node is
598  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
599  * \throw If the coordinates array is not set.
600  * \throw If the nodal connectivity of cells is not defined.
601  * 
602  * \if ENABLE_EXAMPLES
603  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
604  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
605  * \endif
606  */
607 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
608 {
609   checkFullyDefined();
610   int nbOfNodes=getNumberOfNodes();
611   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
612   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
613   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
614   const int *conn=_nodal_connec->getConstPointer();
615   const int *connIndex=_nodal_connec_index->getConstPointer();
616   int nbOfCells=getNumberOfCells();
617   int nbOfEltsInRevNodal=0;
618   for(int eltId=0;eltId<nbOfCells;eltId++)
619     {
620       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
621       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
622       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
623         if(*iter>=0)//for polyhedrons
624           {
625             nbOfEltsInRevNodal++;
626             revNodalIndxPtr[(*iter)+1]++;
627           }
628     }
629   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
630   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
631   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
632   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
633   for(int eltId=0;eltId<nbOfCells;eltId++)
634     {
635       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
636       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
637       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
638         if(*iter>=0)//for polyhedrons
639           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
640     }
641 }
642
643 /// @cond INTERNAL
644
645 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
646 {
647   return id;
648 }
649
650 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
651 {
652   if(!compute)
653     return id+1;
654   else
655     {
656       if(cm.getOrientationStatus(nb,conn1,conn2))
657         return id+1;
658       else
659         return -(id+1);
660     }
661 }
662
663 class MinusOneSonsGenerator
664 {
665 public:
666   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
667   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
668   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
669   static const int DELTA=1;
670 private:
671   const INTERP_KERNEL::CellModel& _cm;
672 };
673
674 class MinusOneSonsGeneratorBiQuadratic
675 {
676 public:
677   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
678   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
679   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
680   static const int DELTA=1;
681 private:
682   const INTERP_KERNEL::CellModel& _cm;
683 };
684
685 class MinusTwoSonsGenerator
686 {
687 public:
688   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
689   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
690   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
691   static const int DELTA=2;
692 private:
693   const INTERP_KERNEL::CellModel& _cm;
694 };
695
696 /// @endcond
697
698 /*!
699  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
700  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
701  * describing correspondence between cells of \a this and the result meshes are
702  * returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending connectivity,
703  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
704  * arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
705  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
706  * \warning For speed reasons, this method does not check if node ids in the nodal
707  *          connectivity correspond to the size of node coordinates array.
708  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
709  *          to write this mesh to the MED file, its cells must be sorted using
710  *          sortCellsInMEDFileFrmt().
711  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
712  *         each cell of \a this mesh.
713  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
714  *        dividing cell ids in \a desc into groups each referring to one
715  *        cell of \a this mesh. Its every element (except the last one) is an index
716  *        pointing to the first id of a group of cells. For example cells of the
717  *        result mesh bounding the cell #1 of \a this mesh are described by following
718  *        range of indices:
719  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
720  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
721  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
722  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
723  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
724  *         by each cell of the result mesh.
725  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
726  *        in the result mesh,
727  *        dividing cell ids in \a revDesc into groups each referring to one
728  *        cell of the result mesh the same way as \a descIndx divides \a desc.
729  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
730  *        delete this mesh using decrRef() as it is no more needed.
731  *  \throw If the coordinates array is not set.
732  *  \throw If the nodal connectivity of cells is node defined.
733  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
734  *         revDescIndx == NULL.
735  * 
736  *  \if ENABLE_EXAMPLES
737  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
738  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
739  *  \endif
740  * \sa buildDescendingConnectivity2()
741  */
742 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
743 {
744   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
745 }
746
747 /*!
748  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
749  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
750  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
751  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
752  * \sa MEDCouplingUMesh::buildDescendingConnectivity
753  */
754 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
755 {
756   checkFullyDefined();
757   if(getMeshDimension()!=3)
758     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
759   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
760 }
761
762 /*!
763  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
764  * this->getMeshDimension(), that bound cells of \a this mesh. In
765  * addition arrays describing correspondence between cells of \a this and the result
766  * meshes are returned. The arrays \a desc and \a descIndx (\ref numbering-indirect) describe the descending
767  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
768  *  mesh. This method differs from buildDescendingConnectivity() in that apart
769  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
770  * result meshes. So a positive id means that order of nodes in corresponding cells
771  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
772  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
773  * i.e. cell ids are one-based.
774  * Arrays \a revDesc and \a revDescIndx (\ref numbering-indirect) describe the reverse descending connectivity,
775  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
776  * \warning For speed reasons, this method does not check if node ids in the nodal
777  *          connectivity correspond to the size of node coordinates array.
778  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
779  *          to write this mesh to the MED file, its cells must be sorted using
780  *          sortCellsInMEDFileFrmt().
781  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
782  *         each cell of \a this mesh.
783  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
784  *        dividing cell ids in \a desc into groups each referring to one
785  *        cell of \a this mesh. Its every element (except the last one) is an index
786  *        pointing to the first id of a group of cells. For example cells of the
787  *        result mesh bounding the cell #1 of \a this mesh are described by following
788  *        range of indices:
789  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
790  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
791  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
792  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
793  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
794  *         by each cell of the result mesh.
795  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
796  *        in the result mesh,
797  *        dividing cell ids in \a revDesc into groups each referring to one
798  *        cell of the result mesh the same way as \a descIndx divides \a desc.
799  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
800  *        shares the node coordinates array with \a this mesh. The caller is to
801  *        delete this mesh using decrRef() as it is no more needed.
802  *  \throw If the coordinates array is not set.
803  *  \throw If the nodal connectivity of cells is node defined.
804  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
805  *         revDescIndx == NULL.
806  * 
807  *  \if ENABLE_EXAMPLES
808  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
809  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
810  *  \endif
811  * \sa buildDescendingConnectivity()
812  */
813 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
814 {
815   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
816 }
817
818 /*!
819  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
820  * For speed reasons no check of this will be done. This method calls
821  * MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
822  * This method lists cell by cell in \b this which are its neighbors. To compute the result
823  * only connectivities are considered.
824  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
825  * The format of return is hence \ref numbering-indirect.
826  *
827  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly
828  * allocated and should be dealt by the caller. \b neighborsIndx 2nd output
829  * parameter allows to select the right part in this array (\ref numbering-indirect). The number of tuples
830  * is equal to the last values in \b neighborsIndx.
831  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be
832  * dealt by the caller. This arrays allow to use the first output parameter \b neighbors (\ref numbering-indirect).
833  */
834 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
835 {
836   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
837   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
838   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
839   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
840   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
841   meshDM1=0;
842   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
843 }
844
845 /*!
846  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm
847  * of MEDCouplingUMesh::computeNeighborsOfCells.
848  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is
849  * typically the case to extract a set a neighbours,
850  * excluding a set of meshdim-1 cells in input descending connectivity.
851  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx (\ref numbering-indirect) input params are
852  * the result of MEDCouplingUMesh::buildDescendingConnectivity.
853  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities
854  * are considered.
855  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
856  *
857  * \param [in] desc descending connectivity array.
858  * \param [in] descIndx descending connectivity index array used to walk through \b desc (\ref numbering-indirect).
859  * \param [in] revDesc reverse descending connectivity array.
860  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc (\ref numbering-indirect).
861  * \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
862  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
863  * \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.
864  */
865 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
866                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
867 {
868   if(!desc || !descIndx || !revDesc || !revDescIndx)
869     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
870   const int *descPtr=desc->getConstPointer();
871   const int *descIPtr=descIndx->getConstPointer();
872   const int *revDescPtr=revDesc->getConstPointer();
873   const int *revDescIPtr=revDescIndx->getConstPointer();
874   //
875   int nbCells=descIndx->getNumberOfTuples()-1;
876   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
878   int *out1Ptr=out1->getPointer();
879   *out1Ptr++=0;
880   out0->reserve(desc->getNumberOfTuples());
881   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
882     {
883       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
884         {
885           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
886           s.erase(i);
887           out0->insertAtTheEnd(s.begin(),s.end());
888         }
889       *out1Ptr=out0->getNumberOfTuples();
890     }
891   neighbors=out0.retn();
892   neighborsIndx=out1.retn();
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 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
911 {
912   checkFullyDefined();
913   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
914   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
915   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
916   switch(mdim)
917   {
918     case 3:
919       {
920         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
921         break;
922       }
923     case 2:
924       {
925         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
926         break;
927       }
928     case 1:
929       {
930         mesh1D=const_cast<MEDCouplingUMesh *>(this);
931         mesh1D->incrRef();
932         break;
933       }
934     default:
935       {
936         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
937       }
938   }
939   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
940   mesh1D->getReverseNodalConnectivity(desc,descIndx);
941   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
942   ret0->alloc(desc->getNumberOfTuples(),1);
943   int *r0Pt(ret0->getPointer());
944   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
945   for(int i=0;i<nbNodes;i++,rni++)
946     {
947       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
948         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
949     }
950   neighbors=ret0.retn();
951   neighborsIdx=descIndx.retn();
952 }
953
954 /// @cond INTERNAL
955
956 /*!
957  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
958  * For speed reasons no check of this will be done.
959  */
960 template<class SonsGenerator>
961 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
962 {
963   if(!desc || !descIndx || !revDesc || !revDescIndx)
964     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
965   checkConnectivityFullyDefined();
966   int nbOfCells=getNumberOfCells();
967   int nbOfNodes=getNumberOfNodes();
968   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
969   int *revNodalIndxPtr=revNodalIndx->getPointer();
970   const int *conn=_nodal_connec->getConstPointer();
971   const int *connIndex=_nodal_connec_index->getConstPointer();
972   std::string name="Mesh constituent of "; name+=getName();
973   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
974   ret->setCoords(getCoords());
975   ret->allocateCells(2*nbOfCells);
976   descIndx->alloc(nbOfCells+1,1);
977   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
978   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
979   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
980     {
981       int pos=connIndex[eltId];
982       int posP1=connIndex[eltId+1];
983       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
984       SonsGenerator sg(cm);
985       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
986       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
987       for(unsigned i=0;i<nbOfSons;i++)
988         {
989           INTERP_KERNEL::NormalizedCellType cmsId;
990           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
991           for(unsigned k=0;k<nbOfNodesSon;k++)
992             if(tmp[k]>=0)
993               revNodalIndxPtr[tmp[k]+1]++;
994           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
995           revDesc2->pushBackSilent(eltId);
996         }
997       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
998     }
999   int nbOfCellsM1=ret->getNumberOfCells();
1000   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
1001   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
1002   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
1003   int *revNodalPtr=revNodal->getPointer();
1004   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
1005   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
1006   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
1007     {
1008       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
1009       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
1010       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
1011         if(*iter>=0)//for polyhedrons
1012           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
1013     }
1014   //
1015   DataArrayInt *commonCells=0,*commonCellsI=0;
1016   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
1017   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1018   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1019   int newNbOfCellsM1=-1;
1020   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
1021                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1022   std::vector<bool> isImpacted(nbOfCellsM1,false);
1023   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1024     for(int work2=work[0];work2!=work[1];work2++)
1025       isImpacted[commonCellsPtr[work2]]=true;
1026   const int *o2nM1Ptr=o2nM1->getConstPointer();
1027   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1028   const int *n2oM1Ptr=n2oM1->getConstPointer();
1029   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1030   ret2->copyTinyInfoFrom(this);
1031   desc->alloc(descIndx->back(),1);
1032   int *descPtr=desc->getPointer();
1033   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1034   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1035     {
1036       if(!isImpacted[i])
1037         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1038       else
1039         {
1040           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1041             {
1042               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1043               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1044             }
1045           else
1046             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1047         }
1048     }
1049   revDesc->reserve(newNbOfCellsM1);
1050   revDescIndx->alloc(newNbOfCellsM1+1,1);
1051   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1052   const int *revDesc2Ptr=revDesc2->getConstPointer();
1053   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1054     {
1055       int oldCellIdM1=n2oM1Ptr[i];
1056       if(!isImpacted[oldCellIdM1])
1057         {
1058           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1059           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1060         }
1061       else
1062         {
1063           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1064             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1065           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1066           commonCellsIPtr++;
1067         }
1068     }
1069   //
1070   return ret2.retn();
1071 }
1072
1073 struct MEDCouplingAccVisit
1074 {
1075   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1076   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1077   int _new_nb_of_nodes;
1078 };
1079
1080 /// @endcond
1081
1082 /*!
1083  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1084  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1085  * array of cell ids. Pay attention that after conversion all algorithms work slower
1086  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1087  * conversion due presence of invalid ids in the array of cells to convert, as a
1088  * result \a this mesh contains some already converted elements. In this case the 2D
1089  * mesh remains valid but 3D mesh becomes \b inconsistent!
1090  *  \warning This method can significantly modify the order of geometric types in \a this,
1091  *          hence, to write this mesh to the MED file, its cells must be sorted using
1092  *          sortCellsInMEDFileFrmt().
1093  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1094  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1095  *         cellIdsToConvertBg.
1096  *  \throw If the coordinates array is not set.
1097  *  \throw If the nodal connectivity of cells is node defined.
1098  *  \throw If dimension of \a this mesh is not either 2 or 3.
1099  *
1100  *  \if ENABLE_EXAMPLES
1101  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1102  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1103  *  \endif
1104  */
1105 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1106 {
1107   checkFullyDefined();
1108   int dim=getMeshDimension();
1109   if(dim<2 || dim>3)
1110     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1111   int nbOfCells(getNumberOfCells());
1112   if(dim==2)
1113     {
1114       const int *connIndex=_nodal_connec_index->getConstPointer();
1115       int *conn=_nodal_connec->getPointer();
1116       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1117         {
1118           if(*iter>=0 && *iter<nbOfCells)
1119             {
1120               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1121               if(!cm.isQuadratic())
1122                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1123               else
1124                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1125             }
1126           else
1127             {
1128               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1129               oss << " in range [0," << nbOfCells << ") !";
1130               throw INTERP_KERNEL::Exception(oss.str().c_str());
1131             }
1132         }
1133     }
1134   else
1135     {
1136       int *connIndex(_nodal_connec_index->getPointer());
1137       const int *connOld(_nodal_connec->getConstPointer());
1138       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1139       std::vector<bool> toBeDone(nbOfCells,false);
1140       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1141         {
1142           if(*iter>=0 && *iter<nbOfCells)
1143             toBeDone[*iter]=true;
1144           else
1145             {
1146               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1147               oss << " in range [0," << nbOfCells << ") !";
1148               throw INTERP_KERNEL::Exception(oss.str().c_str());
1149             }
1150         }
1151       for(int cellId=0;cellId<nbOfCells;cellId++)
1152         {
1153           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1154           int lgthOld(posP1-pos-1);
1155           if(toBeDone[cellId])
1156             {
1157               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1158               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1159               int *tmp(new int[nbOfFaces*lgthOld+1]);
1160               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1161               for(unsigned j=0;j<nbOfFaces;j++)
1162                 {
1163                   INTERP_KERNEL::NormalizedCellType type;
1164                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1165                   work+=offset;
1166                   *work++=-1;
1167                 }
1168               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1169               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1170               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1171               delete [] tmp;
1172             }
1173           else
1174             {
1175               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1176               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1177             }
1178         }
1179       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1180     }
1181   computeTypes();
1182 }
1183
1184 /*!
1185  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1186  * polyhedrons (if \a this is a 3D mesh).
1187  *  \warning As this method is purely for user-friendliness and no optimization is
1188  *          done to avoid construction of a useless vector, this method can be costly
1189  *          in memory.
1190  *  \throw If the coordinates array is not set.
1191  *  \throw If the nodal connectivity of cells is node defined.
1192  *  \throw If dimension of \a this mesh is not either 2 or 3.
1193  */
1194 void MEDCouplingUMesh::convertAllToPoly()
1195 {
1196   int nbOfCells=getNumberOfCells();
1197   std::vector<int> cellIds(nbOfCells);
1198   for(int i=0;i<nbOfCells;i++)
1199     cellIds[i]=i;
1200   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1201 }
1202
1203 /*!
1204  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1205  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1206  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1207  * base facet of the volume and the second half of nodes describes an opposite facet
1208  * having the same number of nodes as the base one. This method converts such
1209  * connectivity to a valid polyhedral format where connectivity of each facet is
1210  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1211  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1212  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1213  * a correct orientation of the first facet of a polyhedron, else orientation of a
1214  * corrected cell is reverse.<br>
1215  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1216  * it releases the user from boring description of polyhedra connectivity in the valid
1217  * format.
1218  *  \throw If \a this->getMeshDimension() != 3.
1219  *  \throw If \a this->getSpaceDimension() != 3.
1220  *  \throw If the nodal connectivity of cells is not defined.
1221  *  \throw If the coordinates array is not set.
1222  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1223  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1224  *
1225  *  \if ENABLE_EXAMPLES
1226  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1227  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1228  *  \endif
1229  */
1230 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1231 {
1232   checkFullyDefined();
1233   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1234     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1235   int nbOfCells=getNumberOfCells();
1236   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1237   newCi->alloc(nbOfCells+1,1);
1238   int *newci=newCi->getPointer();
1239   const int *ci=_nodal_connec_index->getConstPointer();
1240   const int *c=_nodal_connec->getConstPointer();
1241   newci[0]=0;
1242   for(int i=0;i<nbOfCells;i++)
1243     {
1244       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1245       if(type==INTERP_KERNEL::NORM_POLYHED)
1246         {
1247           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1248             {
1249               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1250               throw INTERP_KERNEL::Exception(oss.str().c_str());
1251             }
1252           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1253           if(n2%2!=0)
1254             {
1255               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 !";
1256               throw INTERP_KERNEL::Exception(oss.str().c_str());
1257             }
1258           int n1=(int)(n2/2);
1259           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)
1260         }
1261       else
1262         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1263     }
1264   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1265   newC->alloc(newci[nbOfCells],1);
1266   int *newc=newC->getPointer();
1267   for(int i=0;i<nbOfCells;i++)
1268     {
1269       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1270       if(type==INTERP_KERNEL::NORM_POLYHED)
1271         {
1272           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1273           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1274           *newc++=-1;
1275           for(std::size_t j=0;j<n1;j++)
1276             {
1277               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1278               newc[n1+5*j]=-1;
1279               newc[n1+5*j+1]=c[ci[i]+1+j];
1280               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1281               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1282               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1283             }
1284           newc+=n1*6;
1285         }
1286       else
1287         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1288     }
1289   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1290   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1291 }
1292
1293
1294 /*!
1295  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1296  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1297  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1298  *          to write this mesh to the MED file, its cells must be sorted using
1299  *          sortCellsInMEDFileFrmt().
1300  * \return \c true if at least one cell has been converted, \c false else. In the
1301  *         last case the nodal connectivity remains unchanged.
1302  * \throw If the coordinates array is not set.
1303  * \throw If the nodal connectivity of cells is not defined.
1304  * \throw If \a this->getMeshDimension() < 0.
1305  */
1306 bool MEDCouplingUMesh::unPolyze()
1307 {
1308   checkFullyDefined();
1309   int mdim=getMeshDimension();
1310   if(mdim<0)
1311     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1312   if(mdim<=1)
1313     return false;
1314   int nbOfCells=getNumberOfCells();
1315   if(nbOfCells<1)
1316     return false;
1317   int initMeshLgth=getMeshLength();
1318   int *conn=_nodal_connec->getPointer();
1319   int *index=_nodal_connec_index->getPointer();
1320   int posOfCurCell=0;
1321   int newPos=0;
1322   int lgthOfCurCell;
1323   bool ret=false;
1324   for(int i=0;i<nbOfCells;i++)
1325     {
1326       lgthOfCurCell=index[i+1]-posOfCurCell;
1327       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1328       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1329       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1330       int newLgth;
1331       if(cm.isDynamic())
1332         {
1333           switch(cm.getDimension())
1334           {
1335             case 2:
1336               {
1337                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1338                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1339                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1340                 break;
1341               }
1342             case 3:
1343               {
1344                 int nbOfFaces,lgthOfPolyhConn;
1345                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1346                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1347                 break;
1348               }
1349             case 1:
1350               {
1351                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1352                 break;
1353               }
1354           }
1355           ret=ret || (newType!=type);
1356           conn[newPos]=newType;
1357           newPos+=newLgth+1;
1358           posOfCurCell=index[i+1];
1359           index[i+1]=newPos;
1360         }
1361       else
1362         {
1363           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1364           newPos+=lgthOfCurCell;
1365           posOfCurCell+=lgthOfCurCell;
1366           index[i+1]=newPos;
1367         }
1368     }
1369   if(newPos!=initMeshLgth)
1370     _nodal_connec->reAlloc(newPos);
1371   if(ret)
1372     computeTypes();
1373   return ret;
1374 }
1375
1376 /*!
1377  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1378  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1379  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1380  *
1381  * \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 
1382  *             precision.
1383  */
1384 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1385 {
1386   checkFullyDefined();
1387   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1388     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1389   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1390   coords->recenterForMaxPrecision(eps);
1391   //
1392   int nbOfCells=getNumberOfCells();
1393   const int *conn=_nodal_connec->getConstPointer();
1394   const int *index=_nodal_connec_index->getConstPointer();
1395   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1396   connINew->alloc(nbOfCells+1,1);
1397   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1398   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1399   bool changed=false;
1400   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1401     {
1402       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1403         {
1404           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1405           changed=true;
1406         }
1407       else
1408         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1409       *connINewPtr=connNew->getNumberOfTuples();
1410     }
1411   if(changed)
1412     setConnectivity(connNew,connINew,false);
1413 }
1414
1415 /*!
1416  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1417  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1418  * the format of the returned DataArrayInt instance.
1419  * 
1420  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1421  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1422  */
1423 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1424 {
1425   checkConnectivityFullyDefined();
1426   int nbOfCells=getNumberOfCells();
1427   const int *connIndex=_nodal_connec_index->getConstPointer();
1428   const int *conn=_nodal_connec->getConstPointer();
1429   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1430   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1431   std::vector<bool> retS(maxElt,false);
1432   for(int i=0;i<nbOfCells;i++)
1433     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1434       if(conn[j]>=0)
1435         retS[conn[j]]=true;
1436   int sz=0;
1437   for(int i=0;i<maxElt;i++)
1438     if(retS[i])
1439       sz++;
1440   DataArrayInt *ret=DataArrayInt::New();
1441   ret->alloc(sz,1);
1442   int *retPtr=ret->getPointer();
1443   for(int i=0;i<maxElt;i++)
1444     if(retS[i])
1445       *retPtr++=i;
1446   return ret;
1447 }
1448
1449 /*!
1450  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1451  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1452  */
1453 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1454 {
1455   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1456   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1457   for(int i=0;i<nbOfCells;i++)
1458     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1459       if(conn[j]>=0)
1460         {
1461           if(conn[j]<nbOfNodes)
1462             nodeIdsInUse[conn[j]]=true;
1463           else
1464             {
1465               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1466               throw INTERP_KERNEL::Exception(oss.str().c_str());
1467             }
1468         }
1469 }
1470
1471 /*!
1472  * Finds nodes not used in any cell and returns an array giving a new id to every node
1473  * by excluding the unused nodes, for which the array holds -1. The result array is
1474  * a mapping in "Old to New" mode. 
1475  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1476  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1477  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1478  *          if the node is unused or a new id else. The caller is to delete this
1479  *          array using decrRef() as it is no more needed.  
1480  *  \throw If the coordinates array is not set.
1481  *  \throw If the nodal connectivity of cells is not defined.
1482  *  \throw If the nodal connectivity includes an invalid id.
1483  *
1484  *  \if ENABLE_EXAMPLES
1485  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1486  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1487  *  \endif
1488  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1489  */
1490 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1491 {
1492   nbrOfNodesInUse=-1;
1493   int nbOfNodes(getNumberOfNodes());
1494   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1495   ret->alloc(nbOfNodes,1);
1496   int *traducer=ret->getPointer();
1497   std::fill(traducer,traducer+nbOfNodes,-1);
1498   int nbOfCells=getNumberOfCells();
1499   const int *connIndex=_nodal_connec_index->getConstPointer();
1500   const int *conn=_nodal_connec->getConstPointer();
1501   for(int i=0;i<nbOfCells;i++)
1502     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1503       if(conn[j]>=0)
1504         {
1505           if(conn[j]<nbOfNodes)
1506             traducer[conn[j]]=1;
1507           else
1508             {
1509               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1510               throw INTERP_KERNEL::Exception(oss.str().c_str());
1511             }
1512         }
1513   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1514   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1515   return ret.retn();
1516 }
1517
1518 /*!
1519  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1520  * For each cell in \b this the number of nodes constituting cell is computed.
1521  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1522  * So for pohyhedrons some nodes can be counted several times in the returned result.
1523  * 
1524  * \return a newly allocated array
1525  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1526  */
1527 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1528 {
1529   checkConnectivityFullyDefined();
1530   int nbOfCells=getNumberOfCells();
1531   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1532   ret->alloc(nbOfCells,1);
1533   int *retPtr=ret->getPointer();
1534   const int *conn=getNodalConnectivity()->getConstPointer();
1535   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1536   for(int i=0;i<nbOfCells;i++,retPtr++)
1537     {
1538       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1539         *retPtr=connI[i+1]-connI[i]-1;
1540       else
1541         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1542     }
1543   return ret.retn();
1544 }
1545
1546 /*!
1547  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1548  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1549  *
1550  * \return DataArrayInt * - new object to be deallocated by the caller.
1551  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1552  */
1553 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1554 {
1555   checkConnectivityFullyDefined();
1556   int nbOfCells=getNumberOfCells();
1557   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1558   ret->alloc(nbOfCells,1);
1559   int *retPtr=ret->getPointer();
1560   const int *conn=getNodalConnectivity()->getConstPointer();
1561   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1562   for(int i=0;i<nbOfCells;i++,retPtr++)
1563     {
1564       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1565       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1566         *retPtr=(int)s.size();
1567       else
1568         {
1569           s.erase(-1);
1570           *retPtr=(int)s.size();
1571         }
1572     }
1573   return ret.retn();
1574 }
1575
1576 /*!
1577  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1578  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1579  * 
1580  * \return a newly allocated array
1581  */
1582 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1583 {
1584   checkConnectivityFullyDefined();
1585   int nbOfCells=getNumberOfCells();
1586   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1587   ret->alloc(nbOfCells,1);
1588   int *retPtr=ret->getPointer();
1589   const int *conn=getNodalConnectivity()->getConstPointer();
1590   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1591   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1592     {
1593       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1594       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1595     }
1596   return ret.retn();
1597 }
1598
1599 /*!
1600  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1601  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1602  * array mean that the corresponding old node is no more used. 
1603  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1604  *           this->getNumberOfNodes() before call of this method. The caller is to
1605  *           delete this array using decrRef() as it is no more needed. 
1606  *  \throw If the coordinates array is not set.
1607  *  \throw If the nodal connectivity of cells is not defined.
1608  *  \throw If the nodal connectivity includes an invalid id.
1609  *  \sa areAllNodesFetched
1610  *
1611  *  \if ENABLE_EXAMPLES
1612  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1613  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1614  *  \endif
1615  */
1616 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1617 {
1618   return MEDCouplingPointSet::zipCoordsTraducer();
1619 }
1620
1621 /*!
1622  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1623  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1624  */
1625 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1626 {
1627   switch(compType)
1628   {
1629     case 0:
1630       return AreCellsEqual0(conn,connI,cell1,cell2);
1631     case 1:
1632       return AreCellsEqual1(conn,connI,cell1,cell2);
1633     case 2:
1634       return AreCellsEqual2(conn,connI,cell1,cell2);
1635     case 3:
1636       return AreCellsEqual3(conn,connI,cell1,cell2);
1637     case 7:
1638       return AreCellsEqual7(conn,connI,cell1,cell2);
1639   }
1640   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1641 }
1642
1643 /*!
1644  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1645  */
1646 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1647 {
1648   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1649     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1650   return 0;
1651 }
1652
1653 /*!
1654  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1655  */
1656 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1657 {
1658   int sz=connI[cell1+1]-connI[cell1];
1659   if(sz==connI[cell2+1]-connI[cell2])
1660     {
1661       if(conn[connI[cell1]]==conn[connI[cell2]])
1662         {
1663           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1664           unsigned dim=cm.getDimension();
1665           if(dim!=3)
1666             {
1667               if(dim!=1)
1668                 {
1669                   int sz1=2*(sz-1);
1670                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1671                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1672                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1673                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1674                   return work!=tmp+sz1?1:0;
1675                 }
1676               else
1677                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1678             }
1679           else
1680             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1681         }
1682     }
1683   return 0;
1684 }
1685
1686 /*!
1687  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1688  */
1689 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1690 {
1691   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1692     {
1693       if(conn[connI[cell1]]==conn[connI[cell2]])
1694         {
1695           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1696           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1697           return s1==s2?1:0;
1698         }
1699     }
1700   return 0;
1701 }
1702
1703 /*!
1704  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1705  */
1706 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1707 {
1708   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1709     {
1710       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1711       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1712       return s1==s2?1:0;
1713     }
1714   return 0;
1715 }
1716
1717 /*!
1718  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1719  */
1720 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1721 {
1722   int sz=connI[cell1+1]-connI[cell1];
1723   if(sz==connI[cell2+1]-connI[cell2])
1724     {
1725       if(conn[connI[cell1]]==conn[connI[cell2]])
1726         {
1727           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1728           unsigned dim=cm.getDimension();
1729           if(dim!=3)
1730             {
1731               if(dim!=1)
1732                 {
1733                   int sz1=2*(sz-1);
1734                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1735                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1736                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1737                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1738                   if(work!=tmp+sz1)
1739                     return 1;
1740                   else
1741                     {
1742                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1743                       std::reverse_iterator<int *> it2((int *)tmp);
1744                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1745                         return 2;
1746                       else
1747                         return 0;
1748                     }
1749
1750                   return work!=tmp+sz1?1:0;
1751                 }
1752               else
1753                 {//case of SEG2 and SEG3
1754                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1755                     return 1;
1756                   if(!cm.isQuadratic())
1757                     {
1758                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1759                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1760                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1761                         return 2;
1762                       return 0;
1763                     }
1764                   else
1765                     {
1766                       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])
1767                         return 2;
1768                       return 0;
1769                     }
1770                 }
1771             }
1772           else
1773             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1774         }
1775     }
1776   return 0;
1777 }
1778
1779 /*!
1780  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1781  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1782  * and result remains unchanged.
1783  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1784  * If in 'candidates' pool -1 value is considered as an empty value.
1785  * WARNING this method returns only ONE set of result !
1786  */
1787 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1788 {
1789   if(candidates.size()<1)
1790     return false;
1791   bool ret=false;
1792   std::vector<int>::const_iterator iter=candidates.begin();
1793   int start=(*iter++);
1794   for(;iter!=candidates.end();iter++)
1795     {
1796       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1797       if(status!=0)
1798         {
1799           if(!ret)
1800             {
1801               result->pushBackSilent(start);
1802               ret=true;
1803             }
1804           if(status==1)
1805             result->pushBackSilent(*iter);
1806           else
1807             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1808         }
1809     }
1810   return ret;
1811 }
1812
1813 /*!
1814  * This method find cells that are equal (regarding \a compType) in \a this. The comparison is specified
1815  * by \a compType.
1816  * This method keeps the coordiantes of \a this. This method is time consuming.
1817  *
1818  * \param [in] compType input specifying the technique used to compare cells each other.
1819  *   - 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.
1820  *   - 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)
1821  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1822  *   - 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
1823  * can be used for users not sensitive to orientation of cell
1824  * \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.
1825  * \param [out] commonCellsArr common cells ids (\ref numbering-indirect)
1826  * \param [out] commonCellsIArr common cells ids (\ref numbering-indirect)
1827  * \return the correspondance array old to new in a newly allocated array.
1828  * 
1829  */
1830 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1831 {
1832   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1833   getReverseNodalConnectivity(revNodal,revNodalI);
1834   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1835 }
1836
1837 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1838                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1839 {
1840   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1841   int nbOfCells=nodalI->getNumberOfTuples()-1;
1842   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1843   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1844   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1845   std::vector<bool> isFetched(nbOfCells,false);
1846   if(startCellId==0)
1847     {
1848       for(int i=0;i<nbOfCells;i++)
1849         {
1850           if(!isFetched[i])
1851             {
1852               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1853               std::vector<int> v,v2;
1854               if(connOfNode!=connPtr+connIPtr[i+1])
1855                 {
1856                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1857                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1858                   connOfNode++;
1859                 }
1860               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1861                 if(*connOfNode>=0)
1862                   {
1863                     v=v2;
1864                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1865                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1866                     v2.resize(std::distance(v2.begin(),it));
1867                   }
1868               if(v2.size()>1)
1869                 {
1870                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1871                     {
1872                       int pos=commonCellsI->back();
1873                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1874                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1875                         isFetched[*it]=true;
1876                     }
1877                 }
1878             }
1879         }
1880     }
1881   else
1882     {
1883       for(int i=startCellId;i<nbOfCells;i++)
1884         {
1885           if(!isFetched[i])
1886             {
1887               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1888               std::vector<int> v,v2;
1889               if(connOfNode!=connPtr+connIPtr[i+1])
1890                 {
1891                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1892                   connOfNode++;
1893                 }
1894               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1895                 if(*connOfNode>=0)
1896                   {
1897                     v=v2;
1898                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1899                     v2.resize(std::distance(v2.begin(),it));
1900                   }
1901               if(v2.size()>1)
1902                 {
1903                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1904                     {
1905                       int pos=commonCellsI->back();
1906                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1907                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1908                         isFetched[*it]=true;
1909                     }
1910                 }
1911             }
1912         }
1913     }
1914   commonCellsArr=commonCells.retn();
1915   commonCellsIArr=commonCellsI.retn();
1916 }
1917
1918 /*!
1919  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1920  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1921  * than \a other->getNumberOfCells() in the returned array means that there is no
1922  * corresponding cell in \a this mesh.
1923  * It is expected that \a this and \a other meshes share the same node coordinates
1924  * array, if it is not so an exception is thrown. 
1925  *  \param [in] other - the mesh to compare with.
1926  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1927  *         valid values [0,1,2], see zipConnectivityTraducer().
1928  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1929  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1930  *         values. The caller is to delete this array using
1931  *         decrRef() as it is no more needed.
1932  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1933  *         mesh.
1934  *
1935  *  \if ENABLE_EXAMPLES
1936  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1937  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1938  *  \endif
1939  *  \sa checkDeepEquivalOnSameNodesWith()
1940  *  \sa checkGeoEquivalWith()
1941  */
1942 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1943 {
1944   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1945   int nbOfCells=getNumberOfCells();
1946   static const int possibleCompType[]={0,1,2};
1947   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1948     {
1949       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1950       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1951       oss << " !";
1952       throw INTERP_KERNEL::Exception(oss.str().c_str());
1953     }
1954   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1955   arr=o2n->substr(nbOfCells);
1956   arr->setName(other->getName());
1957   int tmp;
1958   if(other->getNumberOfCells()==0)
1959     return true;
1960   return arr->getMaxValue(tmp)<nbOfCells;
1961 }
1962
1963 /*!
1964  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1965  * This method tries to determine if \b other is fully included in \b this.
1966  * The main difference is that this method is not expected to throw exception.
1967  * This method has two outputs :
1968  *
1969  * \param other other mesh
1970  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1971  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1972  */
1973 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1974 {
1975   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1976   DataArrayInt *commonCells=0,*commonCellsI=0;
1977   int thisNbCells=getNumberOfCells();
1978   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1979   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1980   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1981   int otherNbCells=other->getNumberOfCells();
1982   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1983   arr2->alloc(otherNbCells,1);
1984   arr2->fillWithZero();
1985   int *arr2Ptr=arr2->getPointer();
1986   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1987   for(int i=0;i<nbOfCommon;i++)
1988     {
1989       int start=commonCellsPtr[commonCellsIPtr[i]];
1990       if(start<thisNbCells)
1991         {
1992           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1993             {
1994               int sig=commonCellsPtr[j]>0?1:-1;
1995               int val=std::abs(commonCellsPtr[j])-1;
1996               if(val>=thisNbCells)
1997                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1998             }
1999         }
2000     }
2001   arr2->setName(other->getName());
2002   if(arr2->presenceOfValue(0))
2003     return false;
2004   arr=arr2.retn();
2005   return true;
2006 }
2007
2008 MEDCouplingUMesh *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
2009 {
2010   if(!other)
2011     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
2012   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
2013   if(!otherC)
2014     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
2015   std::vector<const MEDCouplingUMesh *> ms(2);
2016   ms[0]=this;
2017   ms[1]=otherC;
2018   return MergeUMeshesOnSameCoords(ms);
2019 }
2020
2021 /*!
2022  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2023  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2024  * cellIds is not given explicitely but by a range python like.
2025  * 
2026  * \param start
2027  * \param end
2028  * \param step
2029  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
2030  * \return a newly allocated
2031  * 
2032  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2033  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2034  */
2035 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2036 {
2037   if(getMeshDimension()!=-1)
2038     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords));
2039   else
2040     {
2041       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2042       if(newNbOfCells!=1)
2043         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2044       if(start!=0)
2045         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2046       incrRef();
2047       return const_cast<MEDCouplingUMesh *>(this);
2048     }
2049 }
2050
2051 /*!
2052  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2053  * The result mesh shares or not the node coordinates array with \a this mesh depending
2054  * on \a keepCoords parameter.
2055  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2056  *           to write this mesh to the MED file, its cells must be sorted using
2057  *           sortCellsInMEDFileFrmt().
2058  *  \param [in] begin - an array of cell ids to include to the new mesh.
2059  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2060  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2061  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2062  *         by calling zipCoords().
2063  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2064  *         to delete this mesh using decrRef() as it is no more needed. 
2065  *  \throw If the coordinates array is not set.
2066  *  \throw If the nodal connectivity of cells is not defined.
2067  *  \throw If any cell id in the array \a begin is not valid.
2068  *
2069  *  \if ENABLE_EXAMPLES
2070  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2071  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2072  *  \endif
2073  */
2074 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2075 {
2076   if(getMeshDimension()!=-1)
2077     return static_cast<MEDCouplingUMesh *>(MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords));
2078   else
2079     {
2080       if(end-begin!=1)
2081         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2082       if(begin[0]!=0)
2083         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2084       incrRef();
2085       return const_cast<MEDCouplingUMesh *>(this);
2086     }
2087 }
2088
2089 /*!
2090  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2091  *
2092  * 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.
2093  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2094  * The number of cells of \b this will remain the same with this method.
2095  *
2096  * \param [in] cellIdsBg begin of cell ids (included) of cells in this to assign
2097  * \param [in] cellIdsEnd end of cell ids (excluded) of cells in this to assign
2098  * \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 ).
2099  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2100  */
2101 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2102 {
2103   checkConnectivityFullyDefined();
2104   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2105   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2106     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2107   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2108     {
2109       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2110       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2111       throw INTERP_KERNEL::Exception(oss.str().c_str());
2112     }
2113   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2114   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2115     {
2116       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2117       throw INTERP_KERNEL::Exception(oss.str().c_str());
2118     }
2119   int nbOfCells=getNumberOfCells();
2120   bool easyAssign=true;
2121   const int *connI=_nodal_connec_index->getConstPointer();
2122   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2123   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2124     {
2125       if(*it>=0 && *it<nbOfCells)
2126         {
2127           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2128         }
2129       else
2130         {
2131           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2132           throw INTERP_KERNEL::Exception(oss.str().c_str());
2133         }
2134     }
2135   if(easyAssign)
2136     {
2137       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2138       computeTypes();
2139     }
2140   else
2141     {
2142       DataArrayInt *arrOut=0,*arrIOut=0;
2143       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2144                                                arrOut,arrIOut);
2145       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2146       setConnectivity(arrOut,arrIOut,true);
2147     }
2148 }
2149
2150 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2151 {
2152   checkConnectivityFullyDefined();
2153   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2154   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2155     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2156   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2157     {
2158       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2159       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2160       throw INTERP_KERNEL::Exception(oss.str().c_str());
2161     }
2162   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2163   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2164     {
2165       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2166       throw INTERP_KERNEL::Exception(oss.str().c_str());
2167     }
2168   int nbOfCells=getNumberOfCells();
2169   bool easyAssign=true;
2170   const int *connI=_nodal_connec_index->getConstPointer();
2171   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2172   int it=start;
2173   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2174     {
2175       if(it>=0 && it<nbOfCells)
2176         {
2177           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2178         }
2179       else
2180         {
2181           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2182           throw INTERP_KERNEL::Exception(oss.str().c_str());
2183         }
2184     }
2185   if(easyAssign)
2186     {
2187       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2188       computeTypes();
2189     }
2190   else
2191     {
2192       DataArrayInt *arrOut=0,*arrIOut=0;
2193       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2194                                                 arrOut,arrIOut);
2195       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2196       setConnectivity(arrOut,arrIOut,true);
2197     }
2198 }                      
2199
2200 /*!
2201  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2202  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2203  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2204  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2205  *
2206  * \param [in] begin input start of array of node ids.
2207  * \param [in] end input end of array of node ids.
2208  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2209  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2210  */
2211 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2212 {
2213   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2214   checkConnectivityFullyDefined();
2215   int tmp=-1;
2216   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2217   std::vector<bool> fastFinder(sz,false);
2218   for(const int *work=begin;work!=end;work++)
2219     if(*work>=0 && *work<sz)
2220       fastFinder[*work]=true;
2221   int nbOfCells=getNumberOfCells();
2222   const int *conn=getNodalConnectivity()->getConstPointer();
2223   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2224   for(int i=0;i<nbOfCells;i++)
2225     {
2226       int ref=0,nbOfHit=0;
2227       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2228         if(*work2>=0)
2229           {
2230             ref++;
2231             if(fastFinder[*work2])
2232               nbOfHit++;
2233           }
2234       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2235         cellIdsKept->pushBackSilent(i);
2236     }
2237   cellIdsKeptArr=cellIdsKept.retn();
2238 }
2239
2240 /*!
2241  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2242  * this->getMeshDimension(), that bound some cells of \a this mesh.
2243  * The cells of lower dimension to include to the result mesh are selected basing on
2244  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2245  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2246  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2247  * created mesh shares the node coordinates array with \a this mesh. 
2248  *  \param [in] begin - the array of node ids.
2249  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2250  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2251  *         array \a begin are added, else cells whose any node is in the
2252  *         array \a begin are added.
2253  *  \return MEDCouplingUMesh * - new instance of MEDCouplingUMesh. The caller is
2254  *         to delete this mesh using decrRef() as it is no more needed. 
2255  *  \throw If the coordinates array is not set.
2256  *  \throw If the nodal connectivity of cells is not defined.
2257  *  \throw If any node id in \a begin is not valid.
2258  *
2259  *  \if ENABLE_EXAMPLES
2260  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2261  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2262  *  \endif
2263  */
2264 MEDCouplingUMesh *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2265 {
2266   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2267   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2268   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2269   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2270   return static_cast<MEDCouplingUMesh*>(subMesh->buildPartOfMySelfNode(begin,end,fullyIn));
2271 }
2272
2273 /*!
2274  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2275  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2276  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2277  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2278  *         by calling zipCoords().
2279  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is
2280  *         to delete this mesh using decrRef() as it is no more needed. 
2281  *  \throw If the coordinates array is not set.
2282  *  \throw If the nodal connectivity of cells is not defined.
2283  *
2284  *  \if ENABLE_EXAMPLES
2285  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2286  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2287  *  \endif
2288  */
2289 MEDCouplingUMesh *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2290 {
2291   DataArrayInt *desc=DataArrayInt::New();
2292   DataArrayInt *descIndx=DataArrayInt::New();
2293   DataArrayInt *revDesc=DataArrayInt::New();
2294   DataArrayInt *revDescIndx=DataArrayInt::New();
2295   //
2296   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2297   revDesc->decrRef();
2298   desc->decrRef();
2299   descIndx->decrRef();
2300   int nbOfCells=meshDM1->getNumberOfCells();
2301   const int *revDescIndxC=revDescIndx->getConstPointer();
2302   std::vector<int> boundaryCells;
2303   for(int i=0;i<nbOfCells;i++)
2304     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2305       boundaryCells.push_back(i);
2306   revDescIndx->decrRef();
2307   MEDCouplingUMesh *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2308   return ret;
2309 }
2310
2311 /*!
2312  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2313  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2314  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2315  */
2316 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2317 {
2318   checkFullyDefined();
2319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2321   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2322   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2323   //
2324   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2325   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2326   //
2327   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2328   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2329   const int *revDescPtr=revDesc->getConstPointer();
2330   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2331   int nbOfCells=getNumberOfCells();
2332   std::vector<bool> ret1(nbOfCells,false);
2333   int sz=0;
2334   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2335     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2336       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2337   //
2338   DataArrayInt *ret2=DataArrayInt::New();
2339   ret2->alloc(sz,1);
2340   int *ret2Ptr=ret2->getPointer();
2341   sz=0;
2342   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2343     if(*it)
2344       *ret2Ptr++=sz;
2345   ret2->setName("BoundaryCells");
2346   return ret2;
2347 }
2348
2349 /*!
2350  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2351  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2352  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2353  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2354  *
2355  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2356  * 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
2357  * equals a cell in \b otherDimM1OnSameCoords.
2358  *
2359  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2360  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2361  *
2362  * \param [in] otherDimM1OnSameCoords
2363  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2364  * \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
2365  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2366  */
2367 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2368 {
2369   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2370     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2371   checkConnectivityFullyDefined();
2372   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2373   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2374     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2375   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2376   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2377   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2378   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2379   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2380   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2381   DataArrayInt *idsOtherInConsti=0;
2382   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2383   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2384   if(!b)
2385     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2386   std::set<int> s1;
2387   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2388     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2389   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2390   s1arr_renum1->sort();
2391   cellIdsRk0=s0arr.retn();
2392   //cellIdsRk1=s_renum1.retn();
2393   cellIdsRk1=s1arr_renum1.retn();
2394 }
2395
2396 /*!
2397  * 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
2398  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2399  * 
2400  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2401  */
2402 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2403 {
2404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2405   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2406   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2407   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2408   //
2409   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2410   revDesc=0; desc=0; descIndx=0;
2411   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2412   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2413   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2414 }
2415
2416 /*!
2417  * Finds nodes lying on the boundary of \a this mesh.
2418  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2419  *          nodes. The caller is to delete this array using decrRef() as it is no
2420  *          more needed.
2421  *  \throw If the coordinates array is not set.
2422  *  \throw If the nodal connectivity of cells is node defined.
2423  *
2424  *  \if ENABLE_EXAMPLES
2425  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2426  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2427  *  \endif
2428  */
2429 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2430 {
2431   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2432   return skin->computeFetchedNodeIds();
2433 }
2434
2435 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2436 {
2437   incrRef();
2438   return const_cast<MEDCouplingUMesh *>(this);
2439 }
2440
2441 /*!
2442  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2443  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2444  * 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.
2445  * If a node is in the boundary of \b this \b and in the boundary of \b otherDimM1OnSameCoords this node is considerd as needed to be duplicated.
2446  * 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.
2447  *
2448  * \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
2449  *             parameter is altered during the call.
2450  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2451  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2452  * \param [out] cellIdsNotModified cell ids int \b this that lies on \b otherDimM1OnSameCoords mesh whose connectivity do \b not need to be modified as it is the case for \b cellIdsNeededToBeRenum.
2453  *
2454  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2455  */
2456 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2457                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2458 {
2459   typedef MEDCouplingAutoRefCountObjectPtr<DataArrayInt> DAInt;
2460
2461   checkFullyDefined();
2462   otherDimM1OnSameCoords.checkFullyDefined();
2463   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2464     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2465   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2466     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2467   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2468   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2469   DAInt cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2470   DAInt s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2471   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2472   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2473   DAInt s1=m0Part->computeFetchedNodeIds();
2474   DAInt s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2475   DAInt s3=s2->buildSubstraction(s1);
2476   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2477   //
2478   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2479   int nCells2 = m0Part2->getNumberOfCells();
2480   DAInt desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2481   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2482   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2483   DataArrayInt *tmp00=0,*tmp11=0;
2484   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2485   DAInt neighInit00(tmp00);
2486   DAInt neighIInit00(tmp11);
2487   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2488   DataArrayInt *idsTmp=0;
2489   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2490   DAInt ids(idsTmp);
2491   if(!b)
2492     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2493   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2494   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2495   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2496   DataArrayInt *tmp0=0,*tmp1=0;
2497   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2498   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2499   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2500   DAInt neigh00(tmp0);
2501   DAInt neighI00(tmp1);
2502
2503   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2504   int seed = 0, nIter = 0;
2505   int nIterMax = nCells2+1; // Safety net for the loop
2506   DAInt hitCells = DataArrayInt::New(); hitCells->alloc(nCells2);
2507   hitCells->fillWithValue(-1);
2508   DAInt cellsToModifyConn0_torenum = DataArrayInt::New();
2509   cellsToModifyConn0_torenum->alloc(0,1);
2510   while (nIter < nIterMax)
2511     {
2512       DAInt t = hitCells->getIdsEqual(-1);
2513       if (!t->getNumberOfTuples())
2514         break;
2515       // Connex zone without the crack (to compute the next seed really)
2516       int dnu;
2517       DAInt connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2518       int cnt = 0;
2519       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2520         hitCells->setIJ(*ptr,0,1);
2521       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2522       DAInt spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2523       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2524       // Compute next seed, i.e. a cell in another connex part, which was not covered by the previous iterations
2525       DAInt comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2526       DAInt nonHitCells = hitCells->getIdsEqual(-1);
2527       DAInt intersec = nonHitCells->buildIntersection(comple);
2528       if (intersec->getNumberOfTuples())
2529         { seed = intersec->getIJ(0,0); }
2530       else
2531         { break; }
2532       nIter++;
2533     }
2534   if (nIter >= nIterMax)
2535     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2536
2537   DAInt cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2538   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2539   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2540   //
2541   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2542   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2543   nodeIdsToDuplicate=s3.retn();
2544 }
2545
2546 /*!
2547  * This method operates a modification of the connectivity and coords in \b this.
2548  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2549  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2550  * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2551  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2552  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2553  * 
2554  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2555  * 
2556  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2557  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2558  */
2559 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2560 {
2561   int nbOfNodes=getNumberOfNodes();
2562   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2563   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2564 }
2565
2566 /*!
2567  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2568  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2569  *
2570  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2571  *
2572  * \sa renumberNodesInConn
2573  */
2574 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2575 {
2576   checkConnectivityFullyDefined();
2577   int *conn(getNodalConnectivity()->getPointer());
2578   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2579   int nbOfCells(getNumberOfCells());
2580   for(int i=0;i<nbOfCells;i++)
2581     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2582       {
2583         int& node=conn[iconn];
2584         if(node>=0)//avoid polyhedron separator
2585           {
2586             node+=offset;
2587           }
2588       }
2589   _nodal_connec->declareAsNew();
2590   updateTime();
2591 }
2592
2593 /*!
2594  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2595  *  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
2596  *  of a big mesh.
2597  */
2598 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2599 {
2600   checkConnectivityFullyDefined();
2601   int *conn(getNodalConnectivity()->getPointer());
2602   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2603   int nbOfCells(getNumberOfCells());
2604   for(int i=0;i<nbOfCells;i++)
2605     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2606       {
2607         int& node=conn[iconn];
2608         if(node>=0)//avoid polyhedron separator
2609           {
2610             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2611             if(it!=newNodeNumbersO2N.end())
2612               {
2613                 node=(*it).second;
2614               }
2615             else
2616               {
2617                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2618                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2619               }
2620           }
2621       }
2622   _nodal_connec->declareAsNew();
2623   updateTime();
2624 }
2625
2626 /*!
2627  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2628  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2629  * This method is a generalization of shiftNodeNumbersInConn().
2630  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2631  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2632  *         this->getNumberOfNodes(), in "Old to New" mode. 
2633  *         See \ref numbering for more info on renumbering modes.
2634  *  \throw If the nodal connectivity of cells is not defined.
2635  *
2636  *  \if ENABLE_EXAMPLES
2637  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2638  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2639  *  \endif
2640  */
2641 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2642 {
2643   checkConnectivityFullyDefined();
2644   int *conn=getNodalConnectivity()->getPointer();
2645   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2646   int nbOfCells(getNumberOfCells());
2647   for(int i=0;i<nbOfCells;i++)
2648     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2649       {
2650         int& node=conn[iconn];
2651         if(node>=0)//avoid polyhedron separator
2652           {
2653             node=newNodeNumbersO2N[node];
2654           }
2655       }
2656   _nodal_connec->declareAsNew();
2657   updateTime();
2658 }
2659
2660 /*!
2661  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2662  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2663  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2664  * 
2665  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2666  */
2667 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2668 {
2669   checkConnectivityFullyDefined();
2670   int *conn=getNodalConnectivity()->getPointer();
2671   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2672   int nbOfCells=getNumberOfCells();
2673   for(int i=0;i<nbOfCells;i++)
2674     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2675       {
2676         int& node=conn[iconn];
2677         if(node>=0)//avoid polyhedron separator
2678           {
2679             node+=delta;
2680           }
2681       }
2682   _nodal_connec->declareAsNew();
2683   updateTime();
2684 }
2685
2686 /*!
2687  * This method operates a modification of the connectivity in \b this.
2688  * 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.
2689  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2690  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2691  * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2692  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2693  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2694  * 
2695  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2696  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2697  * 
2698  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2699  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2700  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2701  */
2702 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2703 {
2704   checkConnectivityFullyDefined();
2705   std::map<int,int> m;
2706   int val=offset;
2707   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2708     m[*work]=val;
2709   int *conn=getNodalConnectivity()->getPointer();
2710   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2711   int nbOfCells=getNumberOfCells();
2712   for(int i=0;i<nbOfCells;i++)
2713     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2714       {
2715         int& node=conn[iconn];
2716         if(node>=0)//avoid polyhedron separator
2717           {
2718             std::map<int,int>::iterator it=m.find(node);
2719             if(it!=m.end())
2720               node=(*it).second;
2721           }
2722       }
2723   updateTime();
2724 }
2725
2726 /*!
2727  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2728  *
2729  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2730  * After the call of this method the number of cells remains the same as before.
2731  *
2732  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2733  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2734  * be strictly in [0;this->getNumberOfCells()).
2735  *
2736  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2737  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2738  * should be contained in[0;this->getNumberOfCells()).
2739  * 
2740  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2741  * \param check
2742  */
2743 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2744 {
2745   checkConnectivityFullyDefined();
2746   int nbCells=getNumberOfCells();
2747   const int *array=old2NewBg;
2748   if(check)
2749     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2750   //
2751   const int *conn=_nodal_connec->getConstPointer();
2752   const int *connI=_nodal_connec_index->getConstPointer();
2753   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2754   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2755   const int *n2oPtr=n2o->begin();
2756   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2757   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2758   newConn->copyStringInfoFrom(*_nodal_connec);
2759   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2760   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2761   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2762   //
2763   int *newC=newConn->getPointer();
2764   int *newCI=newConnI->getPointer();
2765   int loc=0;
2766   newCI[0]=loc;
2767   for(int i=0;i<nbCells;i++)
2768     {
2769       int pos=n2oPtr[i];
2770       int nbOfElts=connI[pos+1]-connI[pos];
2771       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2772       loc+=nbOfElts;
2773       newCI[i+1]=loc;
2774     }
2775   //
2776   setConnectivity(newConn,newConnI);
2777   if(check)
2778     free(const_cast<int *>(array));
2779 }
2780
2781 /*!
2782  * Finds cells whose bounding boxes intersect a given bounding box.
2783  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2784  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2785  *         zMax (if in 3D). 
2786  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2787  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2788  *         extent of the bounding box of cell to produce an addition to this bounding box.
2789  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2790  *         cells. The caller is to delete this array using decrRef() as it is no more
2791  *         needed. 
2792  *  \throw If the coordinates array is not set.
2793  *  \throw If the nodal connectivity of cells is not defined.
2794  *
2795  *  \if ENABLE_EXAMPLES
2796  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2797  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2798  *  \endif
2799  */
2800 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2801 {
2802   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2803   if(getMeshDimension()==-1)
2804     {
2805       elems->pushBackSilent(0);
2806       return elems.retn();
2807     }
2808   int dim=getSpaceDimension();
2809   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2810   const int* conn      = getNodalConnectivity()->getConstPointer();
2811   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2812   const double* coords = getCoords()->getConstPointer();
2813   int nbOfCells=getNumberOfCells();
2814   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2815     {
2816       for (int i=0; i<dim; i++)
2817         {
2818           elem_bb[i*2]=std::numeric_limits<double>::max();
2819           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2820         }
2821
2822       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2823         {
2824           int node= conn[inode];
2825           if(node>=0)//avoid polyhedron separator
2826             {
2827               for (int idim=0; idim<dim; idim++)
2828                 {
2829                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2830                     {
2831                       elem_bb[idim*2] = coords[node*dim+idim] ;
2832                     }
2833                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2834                     {
2835                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2836                     }
2837                 }
2838             }
2839         }
2840       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2841         elems->pushBackSilent(ielem);
2842     }
2843   return elems.retn();
2844 }
2845
2846 /*!
2847  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2848  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2849  * added in 'elems' parameter.
2850  */
2851 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2852 {
2853   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2854   if(getMeshDimension()==-1)
2855     {
2856       elems->pushBackSilent(0);
2857       return elems.retn();
2858     }
2859   int dim=getSpaceDimension();
2860   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2861   const int* conn      = getNodalConnectivity()->getConstPointer();
2862   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2863   const double* coords = getCoords()->getConstPointer();
2864   int nbOfCells=getNumberOfCells();
2865   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2866     {
2867       for (int i=0; i<dim; i++)
2868         {
2869           elem_bb[i*2]=std::numeric_limits<double>::max();
2870           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2871         }
2872
2873       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2874         {
2875           int node= conn[inode];
2876           if(node>=0)//avoid polyhedron separator
2877             {
2878               for (int idim=0; idim<dim; idim++)
2879                 {
2880                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2881                     {
2882                       elem_bb[idim*2] = coords[node*dim+idim] ;
2883                     }
2884                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2885                     {
2886                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2887                     }
2888                 }
2889             }
2890         }
2891       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2892         elems->pushBackSilent(ielem);
2893     }
2894   return elems.retn();
2895 }
2896
2897 /*!
2898  * Returns a type of a cell by its id.
2899  *  \param [in] cellId - the id of the cell of interest.
2900  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2901  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2902  */
2903 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2904 {
2905   const int *ptI=_nodal_connec_index->getConstPointer();
2906   const int *pt=_nodal_connec->getConstPointer();
2907   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2908     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2909   else
2910     {
2911       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2912       throw INTERP_KERNEL::Exception(oss.str().c_str());
2913     }
2914 }
2915
2916 /*!
2917  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2918  * This method does not throw exception if geometric type \a type is not in \a this.
2919  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2920  * The coordinates array is not considered here.
2921  *
2922  * \param [in] type the geometric type
2923  * \return cell ids in this having geometric type \a type.
2924  */
2925 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2926 {
2927
2928   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2929   ret->alloc(0,1);
2930   checkConnectivityFullyDefined();
2931   int nbCells=getNumberOfCells();
2932   int mdim=getMeshDimension();
2933   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2934   if(mdim!=(int)cm.getDimension())
2935     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2936   const int *ptI=_nodal_connec_index->getConstPointer();
2937   const int *pt=_nodal_connec->getConstPointer();
2938   for(int i=0;i<nbCells;i++)
2939     {
2940       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2941         ret->pushBackSilent(i);
2942     }
2943   return ret.retn();
2944 }
2945
2946 /*!
2947  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2948  */
2949 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2950 {
2951   const int *ptI=_nodal_connec_index->getConstPointer();
2952   const int *pt=_nodal_connec->getConstPointer();
2953   int nbOfCells=getNumberOfCells();
2954   int ret=0;
2955   for(int i=0;i<nbOfCells;i++)
2956     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2957       ret++;
2958   return ret;
2959 }
2960
2961 /*!
2962  * Returns the nodal connectivity of a given cell.
2963  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2964  * all returned node ids can be used in getCoordinatesOfNode().
2965  *  \param [in] cellId - an id of the cell of interest.
2966  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2967  *         cleared before the appending.
2968  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2969  */
2970 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2971 {
2972   const int *ptI=_nodal_connec_index->getConstPointer();
2973   const int *pt=_nodal_connec->getConstPointer();
2974   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2975     if(*w>=0)
2976       conn.push_back(*w);
2977 }
2978
2979 std::string MEDCouplingUMesh::simpleRepr() const
2980 {
2981   static const char msg0[]="No coordinates specified !";
2982   std::ostringstream ret;
2983   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2984   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2985   int tmpp1,tmpp2;
2986   double tt=getTime(tmpp1,tmpp2);
2987   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2988   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2989   if(_mesh_dim>=-1)
2990     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2991   else
2992     { ret << " Mesh dimension has not been set or is invalid !"; }
2993   if(_coords!=0)
2994     {
2995       const int spaceDim=getSpaceDimension();
2996       ret << spaceDim << "\nInfo attached on space dimension : ";
2997       for(int i=0;i<spaceDim;i++)
2998         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2999       ret << "\n";
3000     }
3001   else
3002     ret << msg0 << "\n";
3003   ret << "Number of nodes : ";
3004   if(_coords!=0)
3005     ret << getNumberOfNodes() << "\n";
3006   else
3007     ret << msg0 << "\n";
3008   ret << "Number of cells : ";
3009   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3010     ret << getNumberOfCells() << "\n";
3011   else
3012     ret << "No connectivity specified !" << "\n";
3013   ret << "Cell types present : ";
3014   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
3015     {
3016       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3017       ret << cm.getRepr() << " ";
3018     }
3019   ret << "\n";
3020   return ret.str();
3021 }
3022
3023 std::string MEDCouplingUMesh::advancedRepr() const
3024 {
3025   std::ostringstream ret;
3026   ret << simpleRepr();
3027   ret << "\nCoordinates array : \n___________________\n\n";
3028   if(_coords)
3029     _coords->reprWithoutNameStream(ret);
3030   else
3031     ret << "No array set !\n";
3032   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3033   reprConnectivityOfThisLL(ret);
3034   return ret.str();
3035 }
3036
3037 /*!
3038  * This method returns a C++ code that is a dump of \a this.
3039  * This method will throw if this is not fully defined.
3040  */
3041 std::string MEDCouplingUMesh::cppRepr() const
3042 {
3043   static const char coordsName[]="coords";
3044   static const char connName[]="conn";
3045   static const char connIName[]="connI";
3046   checkFullyDefined();
3047   std::ostringstream ret; ret << "// coordinates" << std::endl;
3048   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3049   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3050   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3051   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3052   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3053   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3054   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3055   return ret.str();
3056 }
3057
3058 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3059 {
3060   std::ostringstream ret;
3061   reprConnectivityOfThisLL(ret);
3062   return ret.str();
3063 }
3064
3065 /*!
3066  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3067  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3068  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3069  * some algos).
3070  * 
3071  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3072  * 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
3073  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3074  */
3075 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3076 {
3077   int mdim=getMeshDimension();
3078   if(mdim<0)
3079     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3080   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3081   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3082   bool needToCpyCT=true;
3083   if(!_nodal_connec)
3084     {
3085       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3086       needToCpyCT=false;
3087     }
3088   else
3089     {
3090       tmp1=_nodal_connec;
3091       tmp1->incrRef();
3092     }
3093   if(!_nodal_connec_index)
3094     {
3095       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3096       needToCpyCT=false;
3097     }
3098   else
3099     {
3100       tmp2=_nodal_connec_index;
3101       tmp2->incrRef();
3102     }
3103   ret->setConnectivity(tmp1,tmp2,false);
3104   if(needToCpyCT)
3105     ret->_types=_types;
3106   if(!_coords)
3107     {
3108       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3109       ret->setCoords(coords);
3110     }
3111   else
3112     ret->setCoords(_coords);
3113   return ret.retn();
3114 }
3115
3116 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3117 {
3118   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3119     {
3120       int nbOfCells=getNumberOfCells();
3121       const int *c=_nodal_connec->getConstPointer();
3122       const int *ci=_nodal_connec_index->getConstPointer();
3123       for(int i=0;i<nbOfCells;i++)
3124         {
3125           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3126           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3127           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3128           stream << "\n";
3129         }
3130     }
3131   else
3132     stream << "Connectivity not defined !\n";
3133 }
3134
3135 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3136 {
3137   const int *ptI=_nodal_connec_index->getConstPointer();
3138   const int *pt=_nodal_connec->getConstPointer();
3139   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3140     return ptI[cellId+1]-ptI[cellId]-1;
3141   else
3142     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3143 }
3144
3145 /*!
3146  * Returns types of cells of the specified part of \a this mesh.
3147  * This method avoids computing sub-mesh explicitely to get its types.
3148  *  \param [in] begin - an array of cell ids of interest.
3149  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3150  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3151  *         describing the cell types. 
3152  *  \throw If the coordinates array is not set.
3153  *  \throw If the nodal connectivity of cells is not defined.
3154  *  \sa getAllGeoTypes()
3155  */
3156 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3157 {
3158   checkFullyDefined();
3159   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3160   const int *conn=_nodal_connec->getConstPointer();
3161   const int *connIndex=_nodal_connec_index->getConstPointer();
3162   for(const int *w=begin;w!=end;w++)
3163     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3164   return ret;
3165 }
3166
3167 /*!
3168  * Defines the nodal connectivity using given connectivity arrays in \ref numbering-indirect format.
3169  * Optionally updates
3170  * a set of types of cells constituting \a this mesh. 
3171  * This method is for advanced users having prepared their connectivity before. For
3172  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3173  *  \param [in] conn - the nodal connectivity array. 
3174  *  \param [in] connIndex - the nodal connectivity index array.
3175  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3176  *         mesh is updated.
3177  */
3178 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3179 {
3180   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3181   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3182   if(isComputingTypes)
3183     computeTypes();
3184   declareAsNew();
3185 }
3186
3187 /*!
3188  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3189  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3190  */
3191 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3192     _nodal_connec(0),_nodal_connec_index(0),
3193     _types(other._types)
3194 {
3195   if(other._nodal_connec)
3196     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3197   if(other._nodal_connec_index)
3198     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3199 }
3200
3201 MEDCouplingUMesh::~MEDCouplingUMesh()
3202 {
3203   if(_nodal_connec)
3204     _nodal_connec->decrRef();
3205   if(_nodal_connec_index)
3206     _nodal_connec_index->decrRef();
3207 }
3208
3209 /*!
3210  * Recomputes a set of cell types of \a this mesh. For more info see
3211  * \ref MEDCouplingUMeshNodalConnectivity.
3212  */
3213 void MEDCouplingUMesh::computeTypes()
3214 {
3215   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3216 }
3217
3218 /*!
3219  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3220  */
3221 void MEDCouplingUMesh::checkFullyDefined() const
3222 {
3223   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3224     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3225 }
3226
3227 /*!
3228  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3229  */
3230 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3231 {
3232   if(!_nodal_connec_index || !_nodal_connec)
3233     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3234 }
3235
3236 /*!
3237  * Returns a number of cells constituting \a this mesh. 
3238  *  \return int - the number of cells in \a this mesh.
3239  *  \throw If the nodal connectivity of cells is not defined.
3240  */
3241 int MEDCouplingUMesh::getNumberOfCells() const
3242
3243   if(_nodal_connec_index)
3244     return _nodal_connec_index->getNumberOfTuples()-1;
3245   else
3246     if(_mesh_dim==-1)
3247       return 1;
3248     else
3249       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3250 }
3251
3252 /*!
3253  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3254  * mesh. For more info see \ref meshes.
3255  *  \return int - the dimension of \a this mesh.
3256  *  \throw If the mesh dimension is not defined using setMeshDimension().
3257  */
3258 int MEDCouplingUMesh::getMeshDimension() const
3259 {
3260   if(_mesh_dim<-1)
3261     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3262   return _mesh_dim;
3263 }
3264
3265 /*!
3266  * Returns a length of the nodal connectivity array.
3267  * This method is for test reason. Normally the integer returned is not useable by
3268  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3269  *  \return int - the length of the nodal connectivity array.
3270  */
3271 int MEDCouplingUMesh::getMeshLength() const
3272 {
3273   return _nodal_connec->getNbOfElems();
3274 }
3275
3276 /*!
3277  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3278  */
3279 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3280 {
3281   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3282   tinyInfo.push_back(getMeshDimension());
3283   tinyInfo.push_back(getNumberOfCells());
3284   if(_nodal_connec)
3285     tinyInfo.push_back(getMeshLength());
3286   else
3287     tinyInfo.push_back(-1);
3288 }
3289
3290 /*!
3291  * First step of unserialization process.
3292  */
3293 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3294 {
3295   return tinyInfo[6]<=0;
3296 }
3297
3298 /*!
3299  * Second step of serialization process.
3300  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3301  * \param a1
3302  * \param a2
3303  * \param littleStrings
3304  */
3305 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3306 {
3307   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3308   if(tinyInfo[5]!=-1)
3309     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3310 }
3311
3312 /*!
3313  * Third and final step of serialization process.
3314  */
3315 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3316 {
3317   MEDCouplingPointSet::serialize(a1,a2);
3318   if(getMeshDimension()>-1)
3319     {
3320       a1=DataArrayInt::New();
3321       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3322       int *ptA1=a1->getPointer();
3323       const int *conn=getNodalConnectivity()->getConstPointer();
3324       const int *index=getNodalConnectivityIndex()->getConstPointer();
3325       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3326       std::copy(conn,conn+getMeshLength(),ptA1);
3327     }
3328   else
3329     a1=0;
3330 }
3331
3332 /*!
3333  * Second and final unserialization process.
3334  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3335  */
3336 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3337 {
3338   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3339   setMeshDimension(tinyInfo[5]);
3340   if(tinyInfo[7]!=-1)
3341     {
3342       // Connectivity
3343       const int *recvBuffer=a1->getConstPointer();
3344       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3345       myConnecIndex->alloc(tinyInfo[6]+1,1);
3346       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3347       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3348       myConnec->alloc(tinyInfo[7],1);
3349       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3350       setConnectivity(myConnec, myConnecIndex);
3351     }
3352 }
3353
3354 /*!
3355  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3356  * CellIds are given using range specified by a start an end and step.
3357  */
3358 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3359 {
3360   checkFullyDefined();
3361   int ncell=getNumberOfCells();
3362   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3363   ret->_mesh_dim=_mesh_dim;
3364   ret->setCoords(_coords);
3365   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3366   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3367   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3368   int work=start;
3369   const int *conn=_nodal_connec->getConstPointer();
3370   const int *connIndex=_nodal_connec_index->getConstPointer();
3371   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3372     {
3373       if(work>=0 && work<ncell)
3374         {
3375           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3376         }
3377       else
3378         {
3379           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3380           throw INTERP_KERNEL::Exception(oss.str().c_str());
3381         }
3382     }
3383   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3384   int *newConnPtr=newConn->getPointer();
3385   std::set<INTERP_KERNEL::NormalizedCellType> types;
3386   work=start;
3387   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3388     {
3389       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3390       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3391     }
3392   ret->setConnectivity(newConn,newConnI,false);
3393   ret->_types=types;
3394   ret->copyTinyInfoFrom(this);
3395   return ret.retn();
3396 }
3397
3398 /*!
3399  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3400  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3401  * The return newly allocated mesh will share the same coordinates as \a this.
3402  */
3403 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3404 {
3405   checkConnectivityFullyDefined();
3406   int ncell=getNumberOfCells();
3407   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3408   ret->_mesh_dim=_mesh_dim;
3409   ret->setCoords(_coords);
3410   std::size_t nbOfElemsRet=std::distance(begin,end);
3411   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3412   connIndexRet[0]=0;
3413   const int *conn=_nodal_connec->getConstPointer();
3414   const int *connIndex=_nodal_connec_index->getConstPointer();
3415   int newNbring=0;
3416   for(const int *work=begin;work!=end;work++,newNbring++)
3417     {
3418       if(*work>=0 && *work<ncell)
3419         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3420       else
3421         {
3422           free(connIndexRet);
3423           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3424           throw INTERP_KERNEL::Exception(oss.str().c_str());
3425         }
3426     }
3427   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3428   int *connRetWork=connRet;
3429   std::set<INTERP_KERNEL::NormalizedCellType> types;
3430   for(const int *work=begin;work!=end;work++)
3431     {
3432       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3433       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3434     }
3435   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3436   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3437   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3438   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3439   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3440   ret->_types=types;
3441   ret->copyTinyInfoFrom(this);
3442   return ret.retn();
3443 }
3444
3445 /*!
3446  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3447  * mesh.<br>
3448  * For 1D cells, the returned field contains lengths.<br>
3449  * For 2D cells, the returned field contains areas.<br>
3450  * For 3D cells, the returned field contains volumes.
3451  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3452  *         orientation, i.e. the volume is always positive.
3453  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3454  *         and one time . The caller is to delete this field using decrRef() as it is no
3455  *         more needed.
3456  */
3457 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3458 {
3459   std::string name="MeasureOfMesh_";
3460   name+=getName();
3461   int nbelem=getNumberOfCells();
3462   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3463   field->setName(name);
3464   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3465   array->alloc(nbelem,1);
3466   double *area_vol=array->getPointer();
3467   field->setArray(array) ; array=0;
3468   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3469   field->synchronizeTimeWithMesh();
3470   if(getMeshDimension()!=-1)
3471     {
3472       int ipt;
3473       INTERP_KERNEL::NormalizedCellType type;
3474       int dim_space=getSpaceDimension();
3475       const double *coords=getCoords()->getConstPointer();
3476       const int *connec=getNodalConnectivity()->getConstPointer();
3477       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3478       for(int iel=0;iel<nbelem;iel++)
3479         {
3480           ipt=connec_index[iel];
3481           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3482           area_vol[iel]=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[iel+1]-ipt-1,coords,dim_space);
3483         }
3484       if(isAbs)
3485         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3486     }
3487   else
3488     {
3489       area_vol[0]=std::numeric_limits<double>::max();
3490     }
3491   return field.retn();
3492 }
3493
3494 /*!
3495  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3496  * mesh.<br>
3497  * For 1D cells, the returned array contains lengths.<br>
3498  * For 2D cells, the returned array contains areas.<br>
3499  * For 3D cells, the returned array contains volumes.
3500  * This method avoids building explicitly a part of \a this mesh to perform the work.
3501  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3502  *         orientation, i.e. the volume is always positive.
3503  *  \param [in] begin - an array of cell ids of interest.
3504  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3505  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3506  *          delete this array using decrRef() as it is no more needed.
3507  * 
3508  *  \if ENABLE_EXAMPLES
3509  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3510  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3511  *  \endif
3512  *  \sa getMeasureField()
3513  */
3514 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3515 {
3516   std::string name="PartMeasureOfMesh_";
3517   name+=getName();
3518   int nbelem=(int)std::distance(begin,end);
3519   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3520   array->setName(name);
3521   array->alloc(nbelem,1);
3522   double *area_vol=array->getPointer();
3523   if(getMeshDimension()!=-1)
3524     {
3525       int ipt;
3526       INTERP_KERNEL::NormalizedCellType type;
3527       int dim_space=getSpaceDimension();
3528       const double *coords=getCoords()->getConstPointer();
3529       const int *connec=getNodalConnectivity()->getConstPointer();
3530       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3531       for(const int *iel=begin;iel!=end;iel++)
3532         {
3533           ipt=connec_index[*iel];
3534           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3535           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3536         }
3537       if(isAbs)
3538         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3539     }
3540   else
3541     {
3542       area_vol[0]=std::numeric_limits<double>::max();
3543     }
3544   return array.retn();
3545 }
3546
3547 /*!
3548  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3549  * \a this one. The returned field contains the dual cell volume for each corresponding
3550  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3551  *  the dual mesh in P1 sens of \a this.<br>
3552  * For 1D cells, the returned field contains lengths.<br>
3553  * For 2D cells, the returned field contains areas.<br>
3554  * For 3D cells, the returned field contains volumes.
3555  * This method is useful to check "P1*" conservative interpolators.
3556  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3557  *         orientation, i.e. the volume is always positive.
3558  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3559  *          nodes and one time. The caller is to delete this array using decrRef() as
3560  *          it is no more needed.
3561  */
3562 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3563 {
3564   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3565   std::string name="MeasureOnNodeOfMesh_";
3566   name+=getName();
3567   int nbNodes=getNumberOfNodes();
3568   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3569   double cst=1./((double)getMeshDimension()+1.);
3570   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3571   array->alloc(nbNodes,1);
3572   double *valsToFill=array->getPointer();
3573   std::fill(valsToFill,valsToFill+nbNodes,0.);
3574   const double *values=tmp->getArray()->getConstPointer();
3575   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3576   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3577   getReverseNodalConnectivity(da,daInd);
3578   const int *daPtr=da->getConstPointer();
3579   const int *daIPtr=daInd->getConstPointer();
3580   for(int i=0;i<nbNodes;i++)
3581     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3582       valsToFill[i]+=cst*values[*cell];
3583   ret->setMesh(this);
3584   ret->setArray(array);
3585   return ret.retn();
3586 }
3587
3588 /*!
3589  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3590  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3591  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3592  * and are normalized.
3593  * <br> \a this can be either 
3594  * - a  2D mesh in 2D or 3D space or 
3595  * - an 1D mesh in 2D space.
3596  * 
3597  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3598  *          cells and one time. The caller is to delete this field using decrRef() as
3599  *          it is no more needed.
3600  *  \throw If the nodal connectivity of cells is not defined.
3601  *  \throw If the coordinates array is not set.
3602  *  \throw If the mesh dimension is not set.
3603  *  \throw If the mesh and space dimension is not as specified above.
3604  */
3605 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3606 {
3607   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3608     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3609   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3610   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3611   int nbOfCells=getNumberOfCells();
3612   int nbComp=getMeshDimension()+1;
3613   array->alloc(nbOfCells,nbComp);
3614   double *vals=array->getPointer();
3615   const int *connI=_nodal_connec_index->getConstPointer();
3616   const int *conn=_nodal_connec->getConstPointer();
3617   const double *coords=_coords->getConstPointer();
3618   if(getMeshDimension()==2)
3619     {
3620       if(getSpaceDimension()==3)
3621         {
3622           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3623           const double *locPtr=loc->getConstPointer();
3624           for(int i=0;i<nbOfCells;i++,vals+=3)
3625             {
3626               int offset=connI[i];
3627               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3628               double n=INTERP_KERNEL::norm<3>(vals);
3629               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3630             }
3631         }
3632       else
3633         {
3634           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3635           const double *isAbsPtr=isAbs->getArray()->begin();
3636           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3637             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3638         }
3639     }
3640   else//meshdimension==1
3641     {
3642       double tmp[2];
3643       for(int i=0;i<nbOfCells;i++)
3644         {
3645           int offset=connI[i];
3646           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3647           double n=INTERP_KERNEL::norm<2>(tmp);
3648           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3649           *vals++=-tmp[1];
3650           *vals++=tmp[0];
3651         }
3652     }
3653   ret->setArray(array);
3654   ret->setMesh(this);
3655   ret->synchronizeTimeWithSupport();
3656   return ret.retn();
3657 }
3658
3659 /*!
3660  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3661  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3662  * and are normalized.
3663  * <br> \a this can be either 
3664  * - a  2D mesh in 2D or 3D space or 
3665  * - an 1D mesh in 2D space.
3666  * 
3667  * This method avoids building explicitly a part of \a this mesh to perform the work.
3668  *  \param [in] begin - an array of cell ids of interest.
3669  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3670  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3671  *          cells and one time. The caller is to delete this field using decrRef() as
3672  *          it is no more needed.
3673  *  \throw If the nodal connectivity of cells is not defined.
3674  *  \throw If the coordinates array is not set.
3675  *  \throw If the mesh dimension is not set.
3676  *  \throw If the mesh and space dimension is not as specified above.
3677  *  \sa buildOrthogonalField()
3678  *
3679  *  \if ENABLE_EXAMPLES
3680  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3681  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3682  *  \endif
3683  */
3684 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3685 {
3686   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3687     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3688   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3689   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3690   std::size_t nbelems=std::distance(begin,end);
3691   int nbComp=getMeshDimension()+1;
3692   array->alloc((int)nbelems,nbComp);
3693   double *vals=array->getPointer();
3694   const int *connI=_nodal_connec_index->getConstPointer();
3695   const int *conn=_nodal_connec->getConstPointer();
3696   const double *coords=_coords->getConstPointer();
3697   if(getMeshDimension()==2)
3698     {
3699       if(getSpaceDimension()==3)
3700         {
3701           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3702           const double *locPtr=loc->getConstPointer();
3703           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3704             {
3705               int offset=connI[*i];
3706               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3707               double n=INTERP_KERNEL::norm<3>(vals);
3708               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3709             }
3710         }
3711       else
3712         {
3713           for(std::size_t i=0;i<nbelems;i++)
3714             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3715         }
3716     }
3717   else//meshdimension==1
3718     {
3719       double tmp[2];
3720       for(const int *i=begin;i!=end;i++)
3721         {
3722           int offset=connI[*i];
3723           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3724           double n=INTERP_KERNEL::norm<2>(tmp);
3725           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3726           *vals++=-tmp[1];
3727           *vals++=tmp[0];
3728         }
3729     }
3730   ret->setArray(array);
3731   ret->setMesh(this);
3732   ret->synchronizeTimeWithSupport();
3733   return ret.retn();
3734 }
3735
3736 /*!
3737  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3738  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3739  * and are \b not normalized.
3740  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3741  *          cells and one time. The caller is to delete this field using decrRef() as
3742  *          it is no more needed.
3743  *  \throw If the nodal connectivity of cells is not defined.
3744  *  \throw If the coordinates array is not set.
3745  *  \throw If \a this->getMeshDimension() != 1.
3746  *  \throw If \a this mesh includes cells of type other than SEG2.
3747  */
3748 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3749 {
3750   if(getMeshDimension()!=1)
3751     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3752   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3753     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3754   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3755   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3756   int nbOfCells=getNumberOfCells();
3757   int spaceDim=getSpaceDimension();
3758   array->alloc(nbOfCells,spaceDim);
3759   double *pt=array->getPointer();
3760   const double *coo=getCoords()->getConstPointer();
3761   std::vector<int> conn;
3762   conn.reserve(2);
3763   for(int i=0;i<nbOfCells;i++)
3764     {
3765       conn.resize(0);
3766       getNodeIdsOfCell(i,conn);
3767       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3768     }
3769   ret->setArray(array);
3770   ret->setMesh(this);
3771   ret->synchronizeTimeWithSupport();
3772   return ret.retn();
3773 }
3774
3775 /*!
3776  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3777  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3778  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3779  * from. If a result face is shared by two 3D cells, then the face in included twice in
3780  * the result mesh.
3781  *  \param [in] origin - 3 components of a point defining location of the plane.
3782  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3783  *         must be greater than 1e-6.
3784  *  \param [in] eps - half-thickness of the plane.
3785  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3786  *         producing correspondent 2D cells. The caller is to delete this array
3787  *         using decrRef() as it is no more needed.
3788  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3789  *         not share the node coordinates array with \a this mesh. The caller is to
3790  *         delete this mesh using decrRef() as it is no more needed.  
3791  *  \throw If the coordinates array is not set.
3792  *  \throw If the nodal connectivity of cells is not defined.
3793  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3794  *  \throw If magnitude of \a vec is less than 1e-6.
3795  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3796  *  \throw If \a this includes quadratic cells.
3797  */
3798 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3799 {
3800   checkFullyDefined();
3801   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3802     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3803   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3804   if(candidates->empty())
3805     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3806   std::vector<int> nodes;
3807   DataArrayInt *cellIds1D=0;
3808   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3809   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3810   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3811   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3812   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3813   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3814   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3815   revDesc2=0; revDescIndx2=0;
3816   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3817   revDesc1=0; revDescIndx1=0;
3818   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3819   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3820   //
3821   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3822   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3823     cut3DCurve[*it]=-1;
3824   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3825   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3826   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3827                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3828                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3829   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3830   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3831   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3832   if(cellIds2->empty())
3833     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3834   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3835   ret->setCoords(mDesc1->getCoords());
3836   ret->setConnectivity(conn,connI,true);
3837   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3838   return ret.retn();
3839 }
3840
3841 /*!
3842  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3843 addition to the mesh, returns a new DataArrayInt, of length equal to the number of 1D cells in the result mesh, holding, for each cell in the result mesh, an id of a 2D cell it comes
3844 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3845 the result mesh.
3846  *  \param [in] origin - 3 components of a point defining location of the plane.
3847  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3848  *         must be greater than 1e-6.
3849  *  \param [in] eps - half-thickness of the plane.
3850  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3851  *         producing correspondent segments. The caller is to delete this array
3852  *         using decrRef() as it is no more needed.
3853  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3854  *         mesh in 3D space. This mesh does not share the node coordinates array with
3855  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3856  *         no more needed. 
3857  *  \throw If the coordinates array is not set.
3858  *  \throw If the nodal connectivity of cells is not defined.
3859  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3860  *  \throw If magnitude of \a vec is less than 1e-6.
3861  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3862  *  \throw If \a this includes quadratic cells.
3863  */
3864 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3865 {
3866   checkFullyDefined();
3867   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3868     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3869   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3870   if(candidates->empty())
3871     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3872   std::vector<int> nodes;
3873   DataArrayInt *cellIds1D=0;
3874   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3875   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3876   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3878   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3879   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3880   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3881   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3882   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3883   //
3884   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3885   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3886     cut3DCurve[*it]=-1;
3887   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3888   int ncellsSub=subMesh->getNumberOfCells();
3889   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3890   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3891                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3892                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3893   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3894   conn->alloc(0,1);
3895   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3896   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3897   for(int i=0;i<ncellsSub;i++)
3898     {
3899       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3900         {
3901           if(cut3DSurf[i].first!=-2)
3902             {
3903               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3904               connI->pushBackSilent(conn->getNumberOfTuples());
3905               cellIds2->pushBackSilent(i);
3906             }
3907           else
3908             {
3909               int cellId3DSurf=cut3DSurf[i].second;
3910               int offset=nodalI[cellId3DSurf]+1;
3911               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3912               for(int j=0;j<nbOfEdges;j++)
3913                 {
3914                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3915                   connI->pushBackSilent(conn->getNumberOfTuples());
3916                   cellIds2->pushBackSilent(cellId3DSurf);
3917                 }
3918             }
3919         }
3920     }
3921   if(cellIds2->empty())
3922     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3923   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3924   ret->setCoords(mDesc1->getCoords());
3925   ret->setConnectivity(conn,connI,true);
3926   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3927   return ret.retn();
3928 }
3929
3930 /*!
3931  * Finds cells whose bounding boxes intersect a given plane.
3932  *  \param [in] origin - 3 components of a point defining location of the plane.
3933  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3934  *         must be greater than 1e-6.
3935  *  \param [in] eps - half-thickness of the plane.
3936  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3937  *         cells. The caller is to delete this array using decrRef() as it is no more
3938  *         needed.
3939  *  \throw If the coordinates array is not set.
3940  *  \throw If the nodal connectivity of cells is not defined.
3941  *  \throw If \a this->getSpaceDimension() != 3.
3942  *  \throw If magnitude of \a vec is less than 1e-6.
3943  *  \sa buildSlice3D()
3944  */
3945 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3946 {
3947   checkFullyDefined();
3948   if(getSpaceDimension()!=3)
3949     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3950   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3951   if(normm<1e-6)
3952     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3953   double vec2[3];
3954   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3955   double angle=acos(vec[2]/normm);
3956   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3957   double bbox[6];
3958   if(angle>eps)
3959     {
3960       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3961       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3962       if(normm2/normm>1e-6)
3963         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3964       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3965       mw->setCoords(coo);
3966       mw->getBoundingBox(bbox);
3967       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3968       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3969     }
3970   else
3971     {
3972       getBoundingBox(bbox);
3973       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3974       cellIds=getCellsInBoundingBox(bbox,eps);
3975     }
3976   return cellIds.retn();
3977 }
3978
3979 /*!
3980  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3981  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3982  * No consideration of coordinate is done by this method.
3983  * 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)
3984  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3985  */
3986 bool MEDCouplingUMesh::isContiguous1D() const
3987 {
3988   if(getMeshDimension()!=1)
3989     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3990   int nbCells=getNumberOfCells();
3991   if(nbCells<1)
3992     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3993   const int *connI=_nodal_connec_index->getConstPointer();
3994   const int *conn=_nodal_connec->getConstPointer();
3995   int ref=conn[connI[0]+2];
3996   for(int i=1;i<nbCells;i++)
3997     {
3998       if(conn[connI[i]+1]!=ref)
3999         return false;
4000       ref=conn[connI[i]+2];
4001     }
4002   return true;
4003 }
4004
4005 /*!
4006  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
4007  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
4008  * \param pt reference point of the line
4009  * \param v normalized director vector of the line
4010  * \param eps max precision before throwing an exception
4011  * \param res output of size this->getNumberOfCells
4012  */
4013 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
4014 {
4015   if(getMeshDimension()!=1)
4016     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
4017   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
4018     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
4019   if(getSpaceDimension()!=3)
4020     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4021   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4022   const double *fPtr=f->getArray()->getConstPointer();
4023   double tmp[3];
4024   for(int i=0;i<getNumberOfCells();i++)
4025     {
4026       const double *tmp1=fPtr+3*i;
4027       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4028       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4029       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4030       double n1=INTERP_KERNEL::norm<3>(tmp);
4031       n1/=INTERP_KERNEL::norm<3>(tmp1);
4032       if(n1>eps)
4033         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4034     }
4035   const double *coo=getCoords()->getConstPointer();
4036   for(int i=0;i<getNumberOfNodes();i++)
4037     {
4038       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4039       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4040       res[i]=std::accumulate(tmp,tmp+3,0.);
4041     }
4042 }
4043
4044 /*!
4045  * 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. 
4046  * \a this is expected to be a mesh so that its space dimension is equal to its
4047  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4048  * 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).
4049  *
4050  * 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
4051  * 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).
4052  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4053  *
4054  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4055  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4056  *
4057  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4058  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4059  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4060  * \return the positive value of the distance.
4061  * \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
4062  * dimension - 1.
4063  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4064  */
4065 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4066 {
4067   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4068   if(meshDim!=spaceDim-1)
4069     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4070   if(meshDim!=2 && meshDim!=1)
4071     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4072   checkFullyDefined();
4073   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4074     { std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoint : input point has to have dimension equal to the space dimension of this (" << spaceDim << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
4075   DataArrayInt *ret1=0;
4076   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4077   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4078   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4079   cellId=*ret1Safe->begin();
4080   return *ret0->begin();
4081 }
4082
4083 /*!
4084  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4085  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4086  * 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
4087  * 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).
4088  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4089  * 
4090  * \a this is expected to be a mesh so that its space dimension is equal to its
4091  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4092  * 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).
4093  *
4094  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4095  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4096  *
4097  * \param [in] pts the list of points in which each tuple represents a point
4098  * \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.
4099  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4100  * \throw if number of components of \a pts is not equal to the space dimension.
4101  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4102  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4103  */
4104 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4105 {
4106   if(!pts)
4107     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4108   pts->checkAllocated();
4109   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4110   if(meshDim!=spaceDim-1)
4111     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4112   if(meshDim!=2 && meshDim!=1)
4113     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4114   if(pts->getNumberOfComponents()!=spaceDim)
4115     {
4116       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4117       throw INTERP_KERNEL::Exception(oss.str().c_str());
4118     }
4119   checkFullyDefined();
4120   int nbCells=getNumberOfCells();
4121   if(nbCells==0)
4122     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4123   int nbOfPts=pts->getNumberOfTuples();
4124   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4125   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4126   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4127   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4128   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4129   const double *bbox(bboxArr->begin());
4130   switch(spaceDim)
4131   {
4132     case 3:
4133       {
4134         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4135         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4136           {
4137             double x=std::numeric_limits<double>::max();
4138             std::vector<int> elems;
4139             myTree.getMinDistanceOfMax(ptsPtr,x);
4140             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4141             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4142           }
4143         break;
4144       }
4145     case 2:
4146       {
4147         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4148         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4149           {
4150             double x=std::numeric_limits<double>::max();
4151             std::vector<int> elems;
4152             myTree.getMinDistanceOfMax(ptsPtr,x);
4153             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4154             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4155           }
4156         break;
4157       }
4158     default:
4159       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4160   }
4161   cellIds=ret1.retn();
4162   return ret0.retn();
4163 }
4164
4165 /// @cond INTERNAL
4166
4167 /*!
4168  * \param [in] pt the start pointer (included) of the coordinates of the point
4169  * \param [in] cellIdsBg the start pointer (included) of cellIds
4170  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4171  * \param [in] nc nodal connectivity
4172  * \param [in] ncI nodal connectivity index
4173  * \param [in,out] ret0 the min distance between \a this and the external input point
4174  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4175  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4176  */
4177 void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId)
4178 {
4179   cellId=-1;
4180   ret0=std::numeric_limits<double>::max();
4181   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4182     {
4183       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4184       {
4185         case INTERP_KERNEL::NORM_TRI3:
4186           {
4187             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4188             if(tmp<ret0)
4189               { ret0=tmp; cellId=*zeCell; }
4190             break;
4191           }
4192         case INTERP_KERNEL::NORM_QUAD4:
4193         case INTERP_KERNEL::NORM_POLYGON:
4194           {
4195             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4196             if(tmp<ret0)
4197               { ret0=tmp; cellId=*zeCell; }
4198             break;
4199           }
4200         default:
4201           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4202       }
4203     }
4204 }
4205
4206 /*!
4207  * \param [in] pt the start pointer (included) of the coordinates of the point
4208  * \param [in] cellIdsBg the start pointer (included) of cellIds
4209  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4210  * \param [in] nc nodal connectivity
4211  * \param [in] ncI nodal connectivity index
4212  * \param [in,out] ret0 the min distance between \a this and the external input point
4213  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4214  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4215  */
4216 void MEDCouplingUMesh::DistanceToPoint2DCurveAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId)
4217 {
4218   cellId=-1;
4219   ret0=std::numeric_limits<double>::max();
4220   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4221     {
4222       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4223       {
4224         case INTERP_KERNEL::NORM_SEG2:
4225           {
4226             std::size_t uselessEntry=0;
4227             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4228             tmp=sqrt(tmp);
4229             if(tmp<ret0)
4230               { ret0=tmp; cellId=*zeCell; }
4231             break;
4232           }
4233         default:
4234           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4235       }
4236     }
4237 }
4238 /// @endcond
4239
4240 /*!
4241  * Finds cells in contact with a ball (i.e. a point with precision). 
4242  * 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.
4243  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4244  *
4245  * \warning This method is suitable if the caller intends to evaluate only one
4246  *          point, for more points getCellsContainingPoints() is recommended as it is
4247  *          faster. 
4248  *  \param [in] pos - array of coordinates of the ball central point.
4249  *  \param [in] eps - ball radius.
4250  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4251  *         if there are no such cells.
4252  *  \throw If the coordinates array is not set.
4253  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4254  */
4255 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4256 {
4257   std::vector<int> elts;
4258   getCellsContainingPoint(pos,eps,elts);
4259   if(elts.empty())
4260     return -1;
4261   return elts.front();
4262 }
4263
4264 /*!
4265  * Finds cells in contact with a ball (i.e. a point with precision).
4266  * 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.
4267  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4268  * \warning This method is suitable if the caller intends to evaluate only one
4269  *          point, for more points getCellsContainingPoints() is recommended as it is
4270  *          faster. 
4271  *  \param [in] pos - array of coordinates of the ball central point.
4272  *  \param [in] eps - ball radius.
4273  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4274  *         before inserting ids.
4275  *  \throw If the coordinates array is not set.
4276  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4277  *
4278  *  \if ENABLE_EXAMPLES
4279  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4280  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4281  *  \endif
4282  */
4283 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4284 {
4285   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4286   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4287   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4288 }
4289
4290 /// @cond INTERNAL
4291
4292 namespace ParaMEDMEM
4293 {
4294   template<const int SPACEDIMM>
4295   class DummyClsMCUG
4296   {
4297   public:
4298     static const int MY_SPACEDIM=SPACEDIMM;
4299     static const int MY_MESHDIM=8;
4300     typedef int MyConnType;
4301     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4302     // begin
4303     // useless, but for windows compilation ...
4304     const double* getCoordinatesPtr() const { return 0; }
4305     const int* getConnectivityPtr() const { return 0; }
4306     const int* getConnectivityIndexPtr() const { return 0; }
4307     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4308     // end
4309   };
4310
4311   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4312   {
4313     INTERP_KERNEL::Edge *ret(0);
4314     MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1]));
4315     m[n0]=bg[0]; m[n1]=bg[1];
4316     switch(typ)
4317     {
4318       case INTERP_KERNEL::NORM_SEG2:
4319         {
4320           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4321           break;
4322         }
4323       case INTERP_KERNEL::NORM_SEG3:
4324         {
4325           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4326           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4327           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4328           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4329           bool colinearity(inters.areColinears());
4330           delete e1; delete e2;
4331           if(colinearity)
4332             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4333           else
4334             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4335           break;
4336         }
4337       default:
4338         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4339     }
4340     return ret;
4341   }
4342
4343   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4344   {
4345     INTERP_KERNEL::Edge *ret=0;
4346     switch(typ)
4347     {
4348       case INTERP_KERNEL::NORM_SEG2:
4349         {
4350           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4351           break;
4352         }
4353       case INTERP_KERNEL::NORM_SEG3:
4354         {
4355           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4356           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4357           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4358           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4359           bool colinearity=inters.areColinears();
4360           delete e1; delete e2;
4361           if(colinearity)
4362             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4363           else
4364             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4365           mapp2[bg[2]].second=false;
4366           break;
4367         }
4368       default:
4369         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4370     }
4371     return ret;
4372   }
4373
4374   /*!
4375    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4376    * the global mesh 'mDesc'.
4377    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4378    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4379    */
4380   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4381                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4382   {
4383     mapp.clear();
4384     std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;//bool is for a flag specifying if node is boundary (true) or only a middle for SEG3.
4385     const double *coo=mDesc->getCoords()->getConstPointer();
4386     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4387     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4388     std::set<int> s;
4389     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4390       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4391     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4392       {
4393         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4394         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4395       }
4396     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4397     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4398       {
4399         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4400         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4401       }
4402     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4403       {
4404         if((*it2).second.second)
4405           mapp[(*it2).second.first]=(*it2).first;
4406         ((*it2).second.first)->decrRef();
4407       }
4408     return ret;
4409   }
4410
4411   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4412   {
4413     if(nodeId>=offset2)
4414       {
4415         int locId=nodeId-offset2;
4416         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4417       }
4418     if(nodeId>=offset1)
4419       {
4420         int locId=nodeId-offset1;
4421         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4422       }
4423     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4424   }
4425
4426   /**
4427    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4428    */
4429   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4430                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4431                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4432   {
4433     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4434       {
4435         int eltId1=abs(*desc1)-1;
4436         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4437           {
4438             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4439             if(it==mappRev.end())
4440               {
4441                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4442                 mapp[node]=*it1;
4443                 mappRev[*it1]=node;
4444               }
4445           }
4446       }
4447   }
4448 }
4449
4450 /// @endcond
4451
4452 template<int SPACEDIM>
4453 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4454                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4455 {
4456   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4457   int *eltsIndexPtr(eltsIndex->getPointer());
4458   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4459   const double *bbox(bboxArr->begin());
4460   int nbOfCells=getNumberOfCells();
4461   const int *conn=_nodal_connec->getConstPointer();
4462   const int *connI=_nodal_connec_index->getConstPointer();
4463   double bb[2*SPACEDIM];
4464   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4465   for(int i=0;i<nbOfPoints;i++)
4466     {
4467       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4468       for(int j=0;j<SPACEDIM;j++)
4469         {
4470           bb[2*j]=pos[SPACEDIM*i+j];
4471           bb[2*j+1]=pos[SPACEDIM*i+j];
4472         }
4473       std::vector<int> candidates;
4474       myTree.getIntersectingElems(bb,candidates);
4475       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4476         {
4477           int sz(connI[(*iter)+1]-connI[*iter]-1);
4478           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4479           bool status(false);
4480           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4481             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4482           else
4483             {
4484               if(SPACEDIM!=2)
4485                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4486               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4487               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4488               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4489               INTERP_KERNEL::QuadraticPolygon *pol(0);
4490               for(int j=0;j<sz;j++)
4491                 {
4492                   int nodeId(conn[connI[*iter]+1+j]);
4493                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4494                 }
4495               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4496                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4497               else
4498                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4499               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4500               double a(0.),b(0.),c(0.);
4501               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4502               status=pol->isInOrOut2(n);
4503               delete pol; n->decrRef();
4504             }
4505           if(status)
4506             {
4507               eltsIndexPtr[i+1]++;
4508               elts->pushBackSilent(*iter);
4509             }
4510         }
4511     }
4512 }
4513 /*!
4514  * Finds cells in contact with several balls (i.e. points with precision).
4515  * This method is an extension of getCellContainingPoint() and
4516  * getCellsContainingPoint() for the case of multiple points.
4517  * 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.
4518  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4519  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4520  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4521  *         this->getSpaceDimension() * \a nbOfPoints 
4522  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4523  *  \param [in] eps - radius of balls (i.e. the precision).
4524  *  \param [out] elts - vector returning ids of found cells.
4525  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4526  *         dividing cell ids in \a elts into groups each referring to one
4527  *         point. Its every element (except the last one) is an index pointing to the
4528  *         first id of a group of cells. For example cells in contact with the *i*-th
4529  *         point are described by following range of indices:
4530  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4531  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4532  *         Number of cells in contact with the *i*-th point is
4533  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4534  *  \throw If the coordinates array is not set.
4535  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4536  *
4537  *  \if ENABLE_EXAMPLES
4538  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4539  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4540  *  \endif
4541  */
4542 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4543                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4544 {
4545   int spaceDim=getSpaceDimension();
4546   int mDim=getMeshDimension();
4547   if(spaceDim==3)
4548     {
4549       if(mDim==3)
4550         {
4551           const double *coords=_coords->getConstPointer();
4552           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4553         }
4554       /*else if(mDim==2)
4555         {
4556
4557         }*/
4558       else
4559         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4560     }
4561   else if(spaceDim==2)
4562     {
4563       if(mDim==2)
4564         {
4565           const double *coords=_coords->getConstPointer();
4566           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4567         }
4568       else
4569         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4570     }
4571   else if(spaceDim==1)
4572     {
4573       if(mDim==1)
4574         {
4575           const double *coords=_coords->getConstPointer();
4576           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4577         }
4578       else
4579         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4580     }
4581   else
4582     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4583 }
4584
4585 /*!
4586  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4587  * least two its edges intersect each other anywhere except their extremities. An
4588  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4589  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4590  *         cleared before filling in.
4591  *  \param [in] eps - precision.
4592  *  \throw If \a this->getMeshDimension() != 2.
4593  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4594  */
4595 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4596 {
4597   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4598   if(getMeshDimension()!=2)
4599     throw INTERP_KERNEL::Exception(msg);
4600   int spaceDim=getSpaceDimension();
4601   if(spaceDim!=2 && spaceDim!=3)
4602     throw INTERP_KERNEL::Exception(msg);
4603   const int *conn=_nodal_connec->getConstPointer();
4604   const int *connI=_nodal_connec_index->getConstPointer();
4605   int nbOfCells=getNumberOfCells();
4606   std::vector<double> cell2DinS2;
4607   for(int i=0;i<nbOfCells;i++)
4608     {
4609       int offset=connI[i];
4610       int nbOfNodesForCell=connI[i+1]-offset-1;
4611       if(nbOfNodesForCell<=3)
4612         continue;
4613       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4614       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4615       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4616         cells.push_back(i);
4617       cell2DinS2.clear();
4618     }
4619 }
4620
4621 /*!
4622  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4623  *
4624  * 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.
4625  * 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.
4626  * 
4627  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4628  * This convex envelop is computed using Jarvis march algorithm.
4629  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4630  * 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)
4631  * 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.
4632  *
4633  * \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.
4634  * \sa MEDCouplingUMesh::colinearize2D
4635  */
4636 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4637 {
4638   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4639     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4640   checkFullyDefined();
4641   const double *coords=getCoords()->getConstPointer();
4642   int nbOfCells=getNumberOfCells();
4643   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4644   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4645   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4646   int *workIndexOut=nodalConnecIndexOut->getPointer();
4647   *workIndexOut=0;
4648   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4649   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4650   std::set<INTERP_KERNEL::NormalizedCellType> types;
4651   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4652   isChanged->alloc(0,1);
4653   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4654     {
4655       int pos=nodalConnecOut->getNumberOfTuples();
4656       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4657         isChanged->pushBackSilent(i);
4658       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4659       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4660     }
4661   if(isChanged->empty())
4662     return 0;
4663   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4664   _types=types;
4665   return isChanged.retn();
4666 }
4667
4668 /*!
4669  * This method is \b NOT const because it can modify \a this.
4670  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4671  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4672  * \param policy specifies the type of extrusion chosen:
4673  *   - \b 0 for translation only (most simple): the cells of the 1D mesh represent the vectors along which the 2D mesh
4674  *   will be repeated to build each level
4675  *   - \b 1 for translation and rotation: the translation is done as above. For each level, an arc of circle is fitted on
4676  *   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
4677  *   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
4678  *   arc.
4679  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4680  */
4681 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4682 {
4683   checkFullyDefined();
4684   mesh1D->checkFullyDefined();
4685   if(!mesh1D->isContiguous1D())
4686     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4687   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4688     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4689   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4690     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4691   if(mesh1D->getMeshDimension()!=1)
4692     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4693   bool isQuad=false;
4694   if(isPresenceOfQuadratic())
4695     {
4696       if(mesh1D->isFullyQuadratic())
4697         isQuad=true;
4698       else
4699         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4700     }
4701   int oldNbOfNodes(getNumberOfNodes());
4702   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4703   switch(policy)
4704   {
4705     case 0:
4706       {
4707         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4708         break;
4709       }
4710     case 1:
4711       {
4712         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4713         break;
4714       }
4715     default:
4716       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4717   }
4718   setCoords(newCoords);
4719   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4720   updateTime();
4721   return ret.retn();
4722 }
4723
4724 /*!
4725  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4726  * If it is not the case an exception will be thrown.
4727  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4728  * intersection of plane defined by ('origin','vec').
4729  * This method has one in/out parameter : 'cut3DCurve'.
4730  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4731  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4732  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4733  * This method will throw an exception if \a this contains a non linear segment.
4734  */
4735 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4736 {
4737   checkFullyDefined();
4738   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4739     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4740   int ncells=getNumberOfCells();
4741   int nnodes=getNumberOfNodes();
4742   double vec2[3],vec3[3],vec4[3];
4743   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4744   if(normm<1e-6)
4745     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4746   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4747   const int *conn=_nodal_connec->getConstPointer();
4748   const int *connI=_nodal_connec_index->getConstPointer();
4749   const double *coo=_coords->getConstPointer();
4750   std::vector<double> addCoo;
4751   for(int i=0;i<ncells;i++)
4752     {
4753       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4754         {
4755           if(cut3DCurve[i]==-2)
4756             {
4757               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4758               vec3[0]=coo[3*endd]-coo[3*st]; vec3[1]=coo[3*endd+1]-coo[3*st+1]; vec3[2]=coo[3*endd+2]-coo[3*st+2];
4759               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4760               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4761               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4762                 {
4763                   const double *st2=coo+3*st;
4764                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4765                   double pos=-(vec4[0]*vec2[0]+vec4[1]*vec2[1]+vec4[2]*vec2[2])/((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2]));
4766                   if(pos>eps && pos<1-eps)
4767                     {
4768                       int nNode=((int)addCoo.size())/3;
4769                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4770                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4771                       cut3DCurve[i]=nnodes+nNode;
4772                     }
4773                 }
4774             }
4775         }
4776       else
4777         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4778     }
4779   if(!addCoo.empty())
4780     {
4781       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4782       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4783       coo2->alloc(newNbOfNodes,3);
4784       double *tmp=coo2->getPointer();
4785       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4786       std::copy(addCoo.begin(),addCoo.end(),tmp);
4787       DataArrayDouble::SetArrayIn(coo2,_coords);
4788     }
4789 }
4790
4791 /*!
4792  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4793  * \param mesh1D is the input 1D mesh used for translation computation.
4794  * \return newCoords new coords filled by this method. 
4795  */
4796 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4797 {
4798   int oldNbOfNodes=getNumberOfNodes();
4799   int nbOf1DCells=mesh1D->getNumberOfCells();
4800   int spaceDim=getSpaceDimension();
4801   DataArrayDouble *ret=DataArrayDouble::New();
4802   std::vector<bool> isQuads;
4803   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4804   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4805   double *retPtr=ret->getPointer();
4806   const double *coords=getCoords()->getConstPointer();
4807   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4808   std::vector<int> v;
4809   std::vector<double> c;
4810   double vec[3];
4811   v.reserve(3);
4812   c.reserve(6);
4813   for(int i=0;i<nbOf1DCells;i++)
4814     {
4815       v.resize(0);
4816       mesh1D->getNodeIdsOfCell(i,v);
4817       c.resize(0);
4818       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4819       mesh1D->getCoordinatesOfNode(v[0],c);
4820       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4821       for(int j=0;j<oldNbOfNodes;j++)
4822         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4823       if(isQuad)
4824         {
4825           c.resize(0);
4826           mesh1D->getCoordinatesOfNode(v[1],c);
4827           mesh1D->getCoordinatesOfNode(v[0],c);
4828           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4829           for(int j=0;j<oldNbOfNodes;j++)
4830             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4831         }
4832     }
4833   ret->copyStringInfoFrom(*getCoords());
4834   return ret;
4835 }
4836
4837 /*!
4838  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4839  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4840  * \return newCoords new coords filled by this method. 
4841  */
4842 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4843 {
4844   if(mesh1D->getSpaceDimension()==2)
4845     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4846   if(mesh1D->getSpaceDimension()==3)
4847     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4848   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4849 }
4850
4851 /*!
4852  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4853  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4854  * \return newCoords new coords filled by this method. 
4855  */
4856 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4857 {
4858   if(isQuad)
4859     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4860   int oldNbOfNodes=getNumberOfNodes();
4861   int nbOf1DCells=mesh1D->getNumberOfCells();
4862   if(nbOf1DCells<2)
4863     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4864   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4865   int nbOfLevsInVec=nbOf1DCells+1;
4866   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4867   double *retPtr=ret->getPointer();
4868   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4869   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4870   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4871   tmp->setCoords(tmp2);
4872   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4873   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4874   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4875   for(int i=1;i<nbOfLevsInVec;i++)
4876     {
4877       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4878       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4879       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4880       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4881       tmp->translate(vec);
4882       double tmp3[2],radius,alpha,alpha0;
4883       const double *p0=i+1<nbOfLevsInVec?begin:third;
4884       const double *p1=i+1<nbOfLevsInVec?end:begin;
4885       const double *p2=i+1<nbOfLevsInVec?third:end;
4886       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4887       double cosangle=i+1<nbOfLevsInVec?(p0[0]-tmp3[0])*(p1[0]-tmp3[0])+(p0[1]-tmp3[1])*(p1[1]-tmp3[1]):(p2[0]-tmp3[0])*(p1[0]-tmp3[0])+(p2[1]-tmp3[1])*(p1[1]-tmp3[1]);
4888       double angle=acos(cosangle/(radius*radius));
4889       tmp->rotate(end,0,angle);
4890       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4891     }
4892   return ret.retn();
4893 }
4894
4895 /*!
4896  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4897  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4898  * \return newCoords new coords filled by this method. 
4899  */
4900 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4901 {
4902   if(isQuad)
4903     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4904   int oldNbOfNodes=getNumberOfNodes();
4905   int nbOf1DCells=mesh1D->getNumberOfCells();
4906   if(nbOf1DCells<2)
4907     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4908   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4909   int nbOfLevsInVec=nbOf1DCells+1;
4910   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4911   double *retPtr=ret->getPointer();
4912   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4913   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4914   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4915   tmp->setCoords(tmp2);
4916   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4917   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4918   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4919   for(int i=1;i<nbOfLevsInVec;i++)
4920     {
4921       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4922       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4923       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4924       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4925       tmp->translate(vec);
4926       double tmp3[2],radius,alpha,alpha0;
4927       const double *p0=i+1<nbOfLevsInVec?begin:third;
4928       const double *p1=i+1<nbOfLevsInVec?end:begin;
4929       const double *p2=i+1<nbOfLevsInVec?third:end;
4930       double vecPlane[3]={
4931         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4932         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4933         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4934       };
4935       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4936       if(norm>1.e-7)
4937         {
4938           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4939           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4940           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4941           double s2=norm2;
4942           double c2=cos(asin(s2));
4943           double m[3][3]={
4944             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4945             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4946             {-vec2[1]*s2, vec2[0]*s2, c2}
4947           };
4948           double p0r[3]={m[0][0]*p0[0]+m[0][1]*p0[1]+m[0][2]*p0[2], m[1][0]*p0[0]+m[1][1]*p0[1]+m[1][2]*p0[2], m[2][0]*p0[0]+m[2][1]*p0[1]+m[2][2]*p0[2]};
4949           double p1r[3]={m[0][0]*p1[0]+m[0][1]*p1[1]+m[0][2]*p1[2], m[1][0]*p1[0]+m[1][1]*p1[1]+m[1][2]*p1[2], m[2][0]*p1[0]+m[2][1]*p1[1]+m[2][2]*p1[2]};
4950           double p2r[3]={m[0][0]*p2[0]+m[0][1]*p2[1]+m[0][2]*p2[2], m[1][0]*p2[0]+m[1][1]*p2[1]+m[1][2]*p2[2], m[2][0]*p2[0]+m[2][1]*p2[1]+m[2][2]*p2[2]};
4951           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4952           double cosangle=i+1<nbOfLevsInVec?(p0r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p0r[1]-tmp3[1])*(p1r[1]-tmp3[1]):(p2r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p2r[1]-tmp3[1])*(p1r[1]-tmp3[1]);
4953           double angle=acos(cosangle/(radius*radius));
4954           tmp->rotate(end,vecPlane,angle);
4955         }
4956       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4957     }
4958   return ret.retn();
4959 }
4960
4961 /*!
4962  * This method is private because not easy to use for end user. This method is const contrary to
4963  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4964  * the coords sorted slice by slice.
4965  * \param isQuad specifies presence of quadratic cells.
4966  */
4967 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4968 {
4969   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4970   int nbOf2DCells(getNumberOfCells());
4971   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4972   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4973   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4974   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4975   newConnI->alloc(nbOf3DCells+1,1);
4976   int *newConnIPtr(newConnI->getPointer());
4977   *newConnIPtr++=0;
4978   std::vector<int> newc;
4979   for(int j=0;j<nbOf2DCells;j++)
4980     {
4981       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4982       *newConnIPtr++=(int)newc.size();
4983     }
4984   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4985   int *newConnPtr(newConn->getPointer());
4986   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4987   newConnIPtr=newConnI->getPointer();
4988   for(int iz=0;iz<nbOf1DCells;iz++)
4989     {
4990       if(iz!=0)
4991         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4992       const int *posOfTypeOfCell(newConnIPtr);
4993       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4994         {
4995           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4996           if(icell!=*posOfTypeOfCell)
4997             {
4998               if(*iter!=-1)
4999                 *newConnPtr=(*iter)+iz*deltaPerLev;
5000               else
5001                 *newConnPtr=-1;
5002             }
5003           else
5004             {
5005               *newConnPtr=*iter;
5006               posOfTypeOfCell++;
5007             }
5008         }
5009     }
5010   ret->setConnectivity(newConn,newConnI,true);
5011   ret->setCoords(getCoords());
5012   return ret;
5013 }
5014
5015 /*!
5016  * Checks if \a this mesh is constituted by only quadratic cells.
5017  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
5018  *  \throw If the coordinates array is not set.
5019  *  \throw If the nodal connectivity of cells is not defined.
5020  */
5021 bool MEDCouplingUMesh::isFullyQuadratic() const
5022 {
5023   checkFullyDefined();
5024   bool ret=true;
5025   int nbOfCells=getNumberOfCells();
5026   for(int i=0;i<nbOfCells && ret;i++)
5027     {
5028       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5029       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5030       ret=cm.isQuadratic();
5031     }
5032   return ret;
5033 }
5034
5035 /*!
5036  * Checks if \a this mesh includes any quadratic cell.
5037  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5038  *  \throw If the coordinates array is not set.
5039  *  \throw If the nodal connectivity of cells is not defined.
5040  */
5041 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5042 {
5043   checkFullyDefined();
5044   bool ret=false;
5045   int nbOfCells=getNumberOfCells();
5046   for(int i=0;i<nbOfCells && !ret;i++)
5047     {
5048       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5049       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5050       ret=cm.isQuadratic();
5051     }
5052   return ret;
5053 }
5054
5055 /*!
5056  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5057  * this mesh, it remains unchanged.
5058  *  \throw If the coordinates array is not set.
5059  *  \throw If the nodal connectivity of cells is not defined.
5060  */
5061 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5062 {
5063   checkFullyDefined();
5064   int nbOfCells=getNumberOfCells();
5065   int delta=0;
5066   const int *iciptr=_nodal_connec_index->getConstPointer();
5067   for(int i=0;i<nbOfCells;i++)
5068     {
5069       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5070       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5071       if(cm.isQuadratic())
5072         {
5073           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5074           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5075           if(!cml.isDynamic())
5076             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5077           else
5078             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5079         }
5080     }
5081   if(delta==0)
5082     return ;
5083   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5084   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5085   const int *icptr=_nodal_connec->getConstPointer();
5086   newConn->alloc(getMeshLength()-delta,1);
5087   newConnI->alloc(nbOfCells+1,1);
5088   int *ocptr=newConn->getPointer();
5089   int *ociptr=newConnI->getPointer();
5090   *ociptr=0;
5091   _types.clear();
5092   for(int i=0;i<nbOfCells;i++,ociptr++)
5093     {
5094       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5095       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5096       if(!cm.isQuadratic())
5097         {
5098           _types.insert(type);
5099           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5100           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5101         }
5102       else
5103         {
5104           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5105           _types.insert(typel);
5106           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5107           int newNbOfNodes=cml.getNumberOfNodes();
5108           if(cml.isDynamic())
5109             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5110           *ocptr++=(int)typel;
5111           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5112           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5113         }
5114     }
5115   setConnectivity(newConn,newConnI,false);
5116 }
5117
5118 /*!
5119  * This method converts all linear cell in \a this to quadratic one.
5120  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5121  * 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)
5122  * 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.
5123  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5124  * end of the existing coordinates.
5125  * 
5126  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5127  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5128  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5129  * 
5130  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5131  *
5132  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5133  */
5134 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5135 {
5136   DataArrayInt *conn=0,*connI=0;
5137   DataArrayDouble *coords=0;
5138   std::set<INTERP_KERNEL::NormalizedCellType> types;
5139   checkFullyDefined();
5140   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5141   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5142   int meshDim=getMeshDimension();
5143   switch(conversionType)
5144   {
5145     case 0:
5146       switch(meshDim)
5147       {
5148         case 1:
5149           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5150           connSafe=conn; connISafe=connI; coordsSafe=coords;
5151           break;
5152         case 2:
5153           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5154           connSafe=conn; connISafe=connI; coordsSafe=coords;
5155           break;
5156         case 3:
5157           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5158           connSafe=conn; connISafe=connI; coordsSafe=coords;
5159           break;
5160         default:
5161           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5162       }
5163       break;
5164         case 1:
5165           {
5166             switch(meshDim)
5167             {
5168               case 1:
5169                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5170                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5171                 break;
5172               case 2:
5173                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5174                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5175                 break;
5176               case 3:
5177                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5178                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5179                 break;
5180               default:
5181                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5182             }
5183             break;
5184           }
5185         default:
5186           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5187   }
5188   setConnectivity(connSafe,connISafe,false);
5189   _types=types;
5190   setCoords(coordsSafe);
5191   return ret.retn();
5192 }
5193
5194 #if 0
5195 /*!
5196  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5197  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5198  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5199  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5200  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5201  * This method can be seen as the opposite method of colinearize2D.
5202  * 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
5203  * to avoid to modify the numbering of existing nodes.
5204  *
5205  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5206  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5207  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5208  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5209  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5210  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5211  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5212  *
5213  * \sa buildDescendingConnectivity2
5214  */
5215 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5216                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5217 {
5218   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5219     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5220   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5221   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5222     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5223   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5224     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5225   //DataArrayInt *out0(0),*outi0(0);
5226   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5227   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5228   //out0s=out0s->buildUnique(); out0s->sort(true);
5229 }
5230 #endif
5231
5232 /*!
5233  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5234  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5235  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5236  */
5237 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5238 {
5239   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5240   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5241   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5242   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5243   int nbOfCells=getNumberOfCells();
5244   int nbOfNodes=getNumberOfNodes();
5245   const int *cPtr=_nodal_connec->getConstPointer();
5246   const int *icPtr=_nodal_connec_index->getConstPointer();
5247   int lastVal=0,offset=nbOfNodes;
5248   for(int i=0;i<nbOfCells;i++,icPtr++)
5249     {
5250       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5251       if(type==INTERP_KERNEL::NORM_SEG2)
5252         {
5253           types.insert(INTERP_KERNEL::NORM_SEG3);
5254           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5255           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5256           newConn->pushBackSilent(offset++);
5257           lastVal+=4;
5258           newConnI->pushBackSilent(lastVal);
5259           ret->pushBackSilent(i);
5260         }
5261       else
5262         {
5263           types.insert(type);
5264           lastVal+=(icPtr[1]-icPtr[0]);
5265           newConnI->pushBackSilent(lastVal);
5266           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5267         }
5268     }
5269   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5270   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5271   return ret.retn();
5272 }
5273
5274 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2DAnd3D0(const MEDCouplingUMesh *m1D, const DataArrayInt *desc, const DataArrayInt *descI, DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5275 {
5276   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5278   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5279   //
5280   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5281   DataArrayInt *conn1D=0,*conn1DI=0;
5282   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5283   DataArrayDouble *coordsTmp=0;
5284   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5285   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5286   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5287   const int *c1DPtr=conn1D->begin();
5288   const int *c1DIPtr=conn1DI->begin();
5289   int nbOfCells=getNumberOfCells();
5290   const int *cPtr=_nodal_connec->getConstPointer();
5291   const int *icPtr=_nodal_connec_index->getConstPointer();
5292   int lastVal=0;
5293   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5294     {
5295       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5296       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5297       if(!cm.isQuadratic())
5298         {
5299           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5300           types.insert(typ2); newConn->pushBackSilent(typ2);
5301           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5302           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5303             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5304           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5305           newConnI->pushBackSilent(lastVal);
5306           ret->pushBackSilent(i);
5307         }
5308       else
5309         {
5310           types.insert(typ);
5311           lastVal+=(icPtr[1]-icPtr[0]);
5312           newConnI->pushBackSilent(lastVal);
5313           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5314         }
5315     }
5316   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5317   return ret.retn();
5318 }
5319
5320 /*!
5321  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5322  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5323  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5324  */
5325 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5326 {
5327   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5328   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5329   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5330 }
5331
5332 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5333 {
5334   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5335   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5336   //
5337   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5338   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5339   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5340   //
5341   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5342   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5343   DataArrayInt *conn1D=0,*conn1DI=0;
5344   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5345   DataArrayDouble *coordsTmp=0;
5346   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5347   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5348   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5349   const int *c1DPtr=conn1D->begin();
5350   const int *c1DIPtr=conn1DI->begin();
5351   int nbOfCells=getNumberOfCells();
5352   const int *cPtr=_nodal_connec->getConstPointer();
5353   const int *icPtr=_nodal_connec_index->getConstPointer();
5354   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5355   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5356     {
5357       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5358       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5359       if(!cm.isQuadratic())
5360         {
5361           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5362           types.insert(typ2); newConn->pushBackSilent(typ2);
5363           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5364           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5365             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5366           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5367           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5368           newConnI->pushBackSilent(lastVal);
5369           ret->pushBackSilent(i);
5370         }
5371       else
5372         {
5373           types.insert(typ);
5374           lastVal+=(icPtr[1]-icPtr[0]);
5375           newConnI->pushBackSilent(lastVal);
5376           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5377         }
5378     }
5379   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5380   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5381   return ret.retn();
5382 }
5383
5384 /*!
5385  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5386  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5387  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5388  */
5389 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5390 {
5391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5392   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5393   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5394 }
5395
5396 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5397 {
5398   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5399   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5400   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5401   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5402   //
5403   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5405   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5406   //
5407   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5408   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5409   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5410   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5411   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5412   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5413   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5414   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5415   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5416   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5417   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5418   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5419   int nbOfCells=getNumberOfCells();
5420   const int *cPtr=_nodal_connec->getConstPointer();
5421   const int *icPtr=_nodal_connec_index->getConstPointer();
5422   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5423   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5424     {
5425       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5426       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5427       if(!cm.isQuadratic())
5428         {
5429           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5430           if(typ2==INTERP_KERNEL::NORM_ERROR)
5431             {
5432               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5433               throw INTERP_KERNEL::Exception(oss.str().c_str());
5434             }
5435           types.insert(typ2); newConn->pushBackSilent(typ2);
5436           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5437           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5438             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5439           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5440             {
5441               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5442               int tmpPos=newConn->getNumberOfTuples();
5443               newConn->pushBackSilent(nodeId2);
5444               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5445             }
5446           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5447           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5448           newConnI->pushBackSilent(lastVal);
5449           ret->pushBackSilent(i);
5450         }
5451       else
5452         {
5453           types.insert(typ);
5454           lastVal+=(icPtr[1]-icPtr[0]);
5455           newConnI->pushBackSilent(lastVal);
5456           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5457         }
5458     }
5459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5461   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5462   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5463   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5464   int *c=newConn->getPointer();
5465   const int *cI(newConnI->begin());
5466   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5467     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5468   offset=coordsTmp2Safe->getNumberOfTuples();
5469   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5470     c[cI[(*elt)+1]-1]+=offset;
5471   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5472   return ret.retn();
5473 }
5474
5475 /*!
5476  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5477  * so that the number of cells remains the same. Quadratic faces are converted to
5478  * polygons. This method works only for 2D meshes in
5479  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5480  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5481  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5482  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5483  *         a polylinized edge constituting the input polygon.
5484  *  \throw If the coordinates array is not set.
5485  *  \throw If the nodal connectivity of cells is not defined.
5486  *  \throw If \a this->getMeshDimension() != 2.
5487  *  \throw If \a this->getSpaceDimension() != 2.
5488  */
5489 void MEDCouplingUMesh::tessellate2D(double eps)
5490 {
5491   checkFullyDefined();
5492   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5493     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5494   double epsa=fabs(eps);
5495   if(epsa<std::numeric_limits<double>::min())
5496     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5497   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5498   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5499   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5500   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5501   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5502   revDesc1=0; revDescIndx1=0;
5503   mDesc->tessellate2DCurve(eps);
5504   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5505   setCoords(mDesc->getCoords());
5506 }
5507
5508 /*!
5509  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5510  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5511  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5512  *         a sub-divided edge.
5513  *  \throw If the coordinates array is not set.
5514  *  \throw If the nodal connectivity of cells is not defined.
5515  *  \throw If \a this->getMeshDimension() != 1.
5516  *  \throw If \a this->getSpaceDimension() != 2.
5517  */
5518 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5519 {
5520   checkFullyDefined();
5521   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5522     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5523   double epsa=fabs(eps);
5524   if(epsa<std::numeric_limits<double>::min())
5525     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5526   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5527   int nbCells=getNumberOfCells();
5528   int nbNodes=getNumberOfNodes();
5529   const int *conn=_nodal_connec->getConstPointer();
5530   const int *connI=_nodal_connec_index->getConstPointer();
5531   const double *coords=_coords->getConstPointer();
5532   std::vector<double> addCoo;
5533   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5534   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5535   newConnI->alloc(nbCells+1,1);
5536   int *newConnIPtr=newConnI->getPointer();
5537   *newConnIPtr=0;
5538   int tmp1[3];
5539   INTERP_KERNEL::Node *tmp2[3];
5540   std::set<INTERP_KERNEL::NormalizedCellType> types;
5541   for(int i=0;i<nbCells;i++,newConnIPtr++)
5542     {
5543       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5544       if(cm.isQuadratic())
5545         {//assert(connI[i+1]-connI[i]-1==3)
5546           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5547           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5548           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5549           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5550           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5551           if(eac)
5552             {
5553               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5554               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5555               delete eac;
5556               newConnIPtr[1]=(int)newConn.size();
5557             }
5558           else
5559             {
5560               types.insert(INTERP_KERNEL::NORM_SEG2);
5561               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5562               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5563               newConnIPtr[1]=newConnIPtr[0]+3;
5564             }
5565         }
5566       else
5567         {
5568           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5569           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5570           newConnIPtr[1]=newConnIPtr[0]+3;
5571         }
5572     }
5573   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5574     return ;
5575   _types=types;
5576   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5577   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5578   newConnArr->alloc((int)newConn.size(),1);
5579   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5580   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5581   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5582   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5583   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5584   std::copy(addCoo.begin(),addCoo.end(),work);
5585   DataArrayDouble::SetArrayIn(newCoords,_coords);
5586   updateTime();
5587 }
5588
5589 /*!
5590  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5591  * In addition, returns an array mapping new cells to old ones. <br>
5592  * This method typically increases the number of cells in \a this mesh
5593  * but the number of nodes remains \b unchanged.
5594  * That's why the 3D splitting policies
5595  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5596  *  \param [in] policy - specifies a pattern used for splitting.
5597  * The semantic of \a policy is:
5598  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5599  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5600  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5601  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5602  *
5603  *
5604  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5605  *          an id of old cell producing it. The caller is to delete this array using
5606  *         decrRef() as it is no more needed.
5607  *
5608  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5609  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5610  *          and \a this->getMeshDimension() != 3. 
5611  *  \throw If \a policy is not one of the four discussed above.
5612  *  \throw If the nodal connectivity of cells is not defined.
5613  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5614  */
5615 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5616 {
5617   switch(policy)
5618   {
5619     case 0:
5620       return simplexizePol0();
5621     case 1:
5622       return simplexizePol1();
5623     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5624         return simplexizePlanarFace5();
5625     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5626         return simplexizePlanarFace6();
5627     default:
5628       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)");
5629   }
5630 }
5631
5632 /*!
5633  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5634  * - 1D: INTERP_KERNEL::NORM_SEG2
5635  * - 2D: INTERP_KERNEL::NORM_TRI3
5636  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5637  *
5638  * This method is useful for users that need to use P1 field services as
5639  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5640  * All these methods need mesh support containing only simplex cells.
5641  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5642  *  \throw If the coordinates array is not set.
5643  *  \throw If the nodal connectivity of cells is not defined.
5644  *  \throw If \a this->getMeshDimension() < 1.
5645  */
5646 bool MEDCouplingUMesh::areOnlySimplexCells() const
5647 {
5648   checkFullyDefined();
5649   int mdim=getMeshDimension();
5650   if(mdim<1 || mdim>3)
5651     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5652   int nbCells=getNumberOfCells();
5653   const int *conn=_nodal_connec->getConstPointer();
5654   const int *connI=_nodal_connec_index->getConstPointer();
5655   for(int i=0;i<nbCells;i++)
5656     {
5657       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5658       if(!cm.isSimplex())
5659         return false;
5660     }
5661   return true;
5662 }
5663
5664 /*!
5665  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5666  */
5667 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5668 {
5669   checkConnectivityFullyDefined();
5670   if(getMeshDimension()!=2)
5671     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5672   int nbOfCells=getNumberOfCells();
5673   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5674   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5675   ret->alloc(nbOfCells+nbOfCutCells,1);
5676   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5677   int *retPt=ret->getPointer();
5678   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5679   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5680   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5681   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5682   int *pt=newConn->getPointer();
5683   int *ptI=newConnI->getPointer();
5684   ptI[0]=0;
5685   const int *oldc=_nodal_connec->getConstPointer();
5686   const int *ci=_nodal_connec_index->getConstPointer();
5687   for(int i=0;i<nbOfCells;i++,ci++)
5688     {
5689       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5690         {
5691           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5692             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5693           pt=std::copy(tmp,tmp+8,pt);
5694           ptI[1]=ptI[0]+4;
5695           ptI[2]=ptI[0]+8;
5696           *retPt++=i;
5697           *retPt++=i;
5698           ptI+=2;
5699         }
5700       else
5701         {
5702           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5703           ptI[1]=ptI[0]+ci[1]-ci[0];
5704           ptI++;
5705           *retPt++=i;
5706         }
5707     }
5708   _nodal_connec->decrRef();
5709   _nodal_connec=newConn.retn();
5710   _nodal_connec_index->decrRef();
5711   _nodal_connec_index=newConnI.retn();
5712   computeTypes();
5713   updateTime();
5714   return ret.retn();
5715 }
5716
5717 /*!
5718  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5719  */
5720 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5721 {
5722   checkConnectivityFullyDefined();
5723   if(getMeshDimension()!=2)
5724     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5725   int nbOfCells=getNumberOfCells();
5726   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5727   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5728   ret->alloc(nbOfCells+nbOfCutCells,1);
5729   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5730   int *retPt=ret->getPointer();
5731   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5732   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5733   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5734   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5735   int *pt=newConn->getPointer();
5736   int *ptI=newConnI->getPointer();
5737   ptI[0]=0;
5738   const int *oldc=_nodal_connec->getConstPointer();
5739   const int *ci=_nodal_connec_index->getConstPointer();
5740   for(int i=0;i<nbOfCells;i++,ci++)
5741     {
5742       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5743         {
5744           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5745             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5746           pt=std::copy(tmp,tmp+8,pt);
5747           ptI[1]=ptI[0]+4;
5748           ptI[2]=ptI[0]+8;
5749           *retPt++=i;
5750           *retPt++=i;
5751           ptI+=2;
5752         }
5753       else
5754         {
5755           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5756           ptI[1]=ptI[0]+ci[1]-ci[0];
5757           ptI++;
5758           *retPt++=i;
5759         }
5760     }
5761   _nodal_connec->decrRef();
5762   _nodal_connec=newConn.retn();
5763   _nodal_connec_index->decrRef();
5764   _nodal_connec_index=newConnI.retn();
5765   computeTypes();
5766   updateTime();
5767   return ret.retn();
5768 }
5769
5770 /*!
5771  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5772  */
5773 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5774 {
5775   checkConnectivityFullyDefined();
5776   if(getMeshDimension()!=3)
5777     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5778   int nbOfCells=getNumberOfCells();
5779   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5780   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5781   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5782   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5783   int *retPt=ret->getPointer();
5784   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5785   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5786   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5787   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5788   int *pt=newConn->getPointer();
5789   int *ptI=newConnI->getPointer();
5790   ptI[0]=0;
5791   const int *oldc=_nodal_connec->getConstPointer();
5792   const int *ci=_nodal_connec_index->getConstPointer();
5793   for(int i=0;i<nbOfCells;i++,ci++)
5794     {
5795       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5796         {
5797           for(int j=0;j<5;j++,pt+=5,ptI++)
5798             {
5799               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5800               pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+3]+1];
5801               *retPt++=i;
5802               ptI[1]=ptI[0]+5;
5803             }
5804         }
5805       else
5806         {
5807           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5808           ptI[1]=ptI[0]+ci[1]-ci[0];
5809           ptI++;
5810           *retPt++=i;
5811         }
5812     }
5813   _nodal_connec->decrRef();
5814   _nodal_connec=newConn.retn();
5815   _nodal_connec_index->decrRef();
5816   _nodal_connec_index=newConnI.retn();
5817   computeTypes();
5818   updateTime();
5819   return ret.retn();
5820 }
5821
5822 /*!
5823  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5824  */
5825 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5826 {
5827   checkConnectivityFullyDefined();
5828   if(getMeshDimension()!=3)
5829     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5830   int nbOfCells=getNumberOfCells();
5831   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5832   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5833   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5834   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5835   int *retPt=ret->getPointer();
5836   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5837   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5838   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5839   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5840   int *pt=newConn->getPointer();
5841   int *ptI=newConnI->getPointer();
5842   ptI[0]=0;
5843   const int *oldc=_nodal_connec->getConstPointer();
5844   const int *ci=_nodal_connec_index->getConstPointer();
5845   for(int i=0;i<nbOfCells;i++,ci++)
5846     {
5847       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5848         {
5849           for(int j=0;j<6;j++,pt+=5,ptI++)
5850             {
5851               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5852               pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+3]+1];
5853               *retPt++=i;
5854               ptI[1]=ptI[0]+5;
5855             }
5856         }
5857       else
5858         {
5859           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5860           ptI[1]=ptI[0]+ci[1]-ci[0];
5861           ptI++;
5862           *retPt++=i;
5863         }
5864     }
5865   _nodal_connec->decrRef();
5866   _nodal_connec=newConn.retn();
5867   _nodal_connec_index->decrRef();
5868   _nodal_connec_index=newConnI.retn();
5869   computeTypes();
5870   updateTime();
5871   return ret.retn();
5872 }
5873
5874 /*!
5875  * This private method is used to subdivide edges of a mesh with meshdim==2. If \a this has no a meshdim equal to 2 an exception will be thrown.
5876  * This method completly ignore coordinates.
5877  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5878  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5879  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5880  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5881  */
5882 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5883 {
5884   checkFullyDefined();
5885   if(getMeshDimension()!=2)
5886     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5887   int nbOfCells=getNumberOfCells();
5888   int *connI=_nodal_connec_index->getPointer();
5889   int newConnLgth=0;
5890   for(int i=0;i<nbOfCells;i++,connI++)
5891     {
5892       int offset=descIndex[i];
5893       int nbOfEdges=descIndex[i+1]-offset;
5894       //
5895       bool ddirect=desc[offset+nbOfEdges-1]>0;
5896       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5897       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5898       for(int j=0;j<nbOfEdges;j++)
5899         {
5900           bool direct=desc[offset+j]>0;
5901           int edgeId=std::abs(desc[offset+j])-1;
5902           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5903             {
5904               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5905               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5906               int ref2=direct?id1:id2;
5907               if(ref==ref2)
5908                 {
5909                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5910                   newConnLgth+=nbOfSubNodes-1;
5911                   ref=direct?id2:id1;
5912                 }
5913               else
5914                 {
5915                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5916                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5917                 }
5918             }
5919           else
5920             {
5921               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5922             }
5923         }
5924       newConnLgth++;//+1 is for cell type
5925       connI[1]=newConnLgth;
5926     }
5927   //
5928   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5929   newConn->alloc(newConnLgth,1);
5930   int *work=newConn->getPointer();
5931   for(int i=0;i<nbOfCells;i++)
5932     {
5933       *work++=INTERP_KERNEL::NORM_POLYGON;
5934       int offset=descIndex[i];
5935       int nbOfEdges=descIndex[i+1]-offset;
5936       for(int j=0;j<nbOfEdges;j++)
5937         {
5938           bool direct=desc[offset+j]>0;
5939           int edgeId=std::abs(desc[offset+j])-1;
5940           if(direct)
5941             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5942           else
5943             {
5944               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5945               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5946               work=std::copy(it,it+nbOfSubNodes-1,work);
5947             }
5948         }
5949     }
5950   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5951   _types.clear();
5952   if(nbOfCells>0)
5953     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5954 }
5955
5956 /*!
5957  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5958  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5959  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5960  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5961  * so it can be useful to call mergeNodes() before calling this method.
5962  *  \throw If \a this->getMeshDimension() <= 1.
5963  *  \throw If the coordinates array is not set.
5964  *  \throw If the nodal connectivity of cells is not defined.
5965  */
5966 void MEDCouplingUMesh::convertDegeneratedCells()
5967 {
5968   checkFullyDefined();
5969   if(getMeshDimension()<=1)
5970     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5971   int nbOfCells=getNumberOfCells();
5972   if(nbOfCells<1)
5973     return ;
5974   int initMeshLgth=getMeshLength();
5975   int *conn=_nodal_connec->getPointer();
5976   int *index=_nodal_connec_index->getPointer();
5977   int posOfCurCell=0;
5978   int newPos=0;
5979   int lgthOfCurCell;
5980   for(int i=0;i<nbOfCells;i++)
5981     {
5982       lgthOfCurCell=index[i+1]-posOfCurCell;
5983       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5984       int newLgth;
5985       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5986                                                                                                      conn+newPos+1,newLgth);
5987       conn[newPos]=newType;
5988       newPos+=newLgth+1;
5989       posOfCurCell=index[i+1];
5990       index[i+1]=newPos;
5991     }
5992   if(newPos!=initMeshLgth)
5993     _nodal_connec->reAlloc(newPos);
5994   computeTypes();
5995 }
5996
5997 /*!
5998  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5999  * A cell is considered to be oriented correctly if an angle between its
6000  * normal vector and a given vector is less than \c PI / \c 2.
6001  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6002  *         cells. 
6003  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6004  *         checked.
6005  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6006  *         is not cleared before filling in.
6007  *  \throw If \a this->getMeshDimension() != 2.
6008  *  \throw If \a this->getSpaceDimension() != 3.
6009  *
6010  *  \if ENABLE_EXAMPLES
6011  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6012  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6013  *  \endif
6014  */
6015 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
6016 {
6017   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6018     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
6019   int nbOfCells=getNumberOfCells();
6020   const int *conn=_nodal_connec->getConstPointer();
6021   const int *connI=_nodal_connec_index->getConstPointer();
6022   const double *coordsPtr=_coords->getConstPointer();
6023   for(int i=0;i<nbOfCells;i++)
6024     {
6025       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6026       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6027         {
6028           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6029           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6030             cells.push_back(i);
6031         }
6032     }
6033 }
6034
6035 /*!
6036  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6037  * considered to be oriented correctly if an angle between its normal vector and a
6038  * given vector is less than \c PI / \c 2. 
6039  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6040  *         cells. 
6041  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6042  *         checked.
6043  *  \throw If \a this->getMeshDimension() != 2.
6044  *  \throw If \a this->getSpaceDimension() != 3.
6045  *
6046  *  \if ENABLE_EXAMPLES
6047  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6048  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6049  *  \endif
6050  *
6051  *  \sa changeOrientationOfCells
6052  */
6053 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6054 {
6055   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6056     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6057   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6058   const int *connI(_nodal_connec_index->getConstPointer());
6059   const double *coordsPtr(_coords->getConstPointer());
6060   bool isModified(false);
6061   for(int i=0;i<nbOfCells;i++)
6062     {
6063       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6064       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6065         {
6066           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6067           bool isQuadratic(cm.isQuadratic());
6068           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6069             {
6070               isModified=true;
6071               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6072             }
6073         }
6074     }
6075   if(isModified)
6076     _nodal_connec->declareAsNew();
6077   updateTime();
6078 }
6079
6080 /*!
6081  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6082  *
6083  * \sa orientCorrectly2DCells
6084  */
6085 void MEDCouplingUMesh::changeOrientationOfCells()
6086 {
6087   int mdim(getMeshDimension());
6088   if(mdim!=2 && mdim!=1)
6089     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6090   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6091   const int *connI(_nodal_connec_index->getConstPointer());
6092   if(mdim==2)
6093     {//2D
6094       for(int i=0;i<nbOfCells;i++)
6095         {
6096           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6097           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6098           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6099         }
6100     }
6101   else
6102     {//1D
6103       for(int i=0;i<nbOfCells;i++)
6104         {
6105           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6106           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6107           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6108         }
6109     }
6110 }
6111
6112 /*!
6113  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6114  * oriented facets. The normal vector of the facet should point out of the cell.
6115  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6116  *         is not cleared before filling in.
6117  *  \throw If \a this->getMeshDimension() != 3.
6118  *  \throw If \a this->getSpaceDimension() != 3.
6119  *  \throw If the coordinates array is not set.
6120  *  \throw If the nodal connectivity of cells is not defined.
6121  *
6122  *  \if ENABLE_EXAMPLES
6123  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6124  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6125  *  \endif
6126  */
6127 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6128 {
6129   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6130     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6131   int nbOfCells=getNumberOfCells();
6132   const int *conn=_nodal_connec->getConstPointer();
6133   const int *connI=_nodal_connec_index->getConstPointer();
6134   const double *coordsPtr=_coords->getConstPointer();
6135   for(int i=0;i<nbOfCells;i++)
6136     {
6137       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6138       if(type==INTERP_KERNEL::NORM_POLYHED)
6139         {
6140           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6141             cells.push_back(i);
6142         }
6143     }
6144 }
6145
6146 /*!
6147  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6148  * out of the cell. 
6149  *  \throw If \a this->getMeshDimension() != 3.
6150  *  \throw If \a this->getSpaceDimension() != 3.
6151  *  \throw If the coordinates array is not set.
6152  *  \throw If the nodal connectivity of cells is not defined.
6153  *  \throw If the reparation fails.
6154  *
6155  *  \if ENABLE_EXAMPLES
6156  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6157  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6158  *  \endif
6159  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6160  */
6161 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6162 {
6163   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6164     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6165   int nbOfCells=getNumberOfCells();
6166   int *conn=_nodal_connec->getPointer();
6167   const int *connI=_nodal_connec_index->getConstPointer();
6168   const double *coordsPtr=_coords->getConstPointer();
6169   for(int i=0;i<nbOfCells;i++)
6170     {
6171       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6172       if(type==INTERP_KERNEL::NORM_POLYHED)
6173         {
6174           try
6175           {
6176               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6177                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6178           }
6179           catch(INTERP_KERNEL::Exception& e)
6180           {
6181               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6182               throw INTERP_KERNEL::Exception(oss.str().c_str());
6183           }
6184         }
6185     }
6186   updateTime();
6187 }
6188
6189 /*!
6190  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6191  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6192  * according to which the first facet of the cell should be oriented to have the normal vector
6193  * pointing out of cell.
6194  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6195  *         cells. The caller is to delete this array using decrRef() as it is no more
6196  *         needed. 
6197  *  \throw If \a this->getMeshDimension() != 3.
6198  *  \throw If \a this->getSpaceDimension() != 3.
6199  *  \throw If the coordinates array is not set.
6200  *  \throw If the nodal connectivity of cells is not defined.
6201  *
6202  *  \if ENABLE_EXAMPLES
6203  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6204  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6205  *  \endif
6206  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6207  */
6208 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6209 {
6210   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6211   if(getMeshDimension()!=3)
6212     throw INTERP_KERNEL::Exception(msg);
6213   int spaceDim=getSpaceDimension();
6214   if(spaceDim!=3)
6215     throw INTERP_KERNEL::Exception(msg);
6216   //
6217   int nbOfCells=getNumberOfCells();
6218   int *conn=_nodal_connec->getPointer();
6219   const int *connI=_nodal_connec_index->getConstPointer();
6220   const double *coo=getCoords()->getConstPointer();
6221   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6222   for(int i=0;i<nbOfCells;i++)
6223     {
6224       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6225       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6226         {
6227           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6228             {
6229               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6230               cells->pushBackSilent(i);
6231             }
6232         }
6233     }
6234   return cells.retn();
6235 }
6236
6237 /*!
6238  * This method is a faster method to correct orientation of all 3D cells in \a this.
6239  * 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.
6240  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6241  * 
6242  * \return a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6243  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6244  */
6245 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6246 {
6247   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6248     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6249   int nbOfCells=getNumberOfCells();
6250   int *conn=_nodal_connec->getPointer();
6251   const int *connI=_nodal_connec_index->getConstPointer();
6252   const double *coordsPtr=_coords->getConstPointer();
6253   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6254   for(int i=0;i<nbOfCells;i++)
6255     {
6256       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6257       switch(type)
6258       {
6259         case INTERP_KERNEL::NORM_TETRA4:
6260           {
6261             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6262               {
6263                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6264                 ret->pushBackSilent(i);
6265               }
6266             break;
6267           }
6268         case INTERP_KERNEL::NORM_PYRA5:
6269           {
6270             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6271               {
6272                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6273                 ret->pushBackSilent(i);
6274               }
6275             break;
6276           }
6277         case INTERP_KERNEL::NORM_PENTA6:
6278         case INTERP_KERNEL::NORM_HEXA8:
6279         case INTERP_KERNEL::NORM_HEXGP12:
6280           {
6281             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6282               {
6283                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6284                 ret->pushBackSilent(i);
6285               }
6286             break;
6287           }
6288         case INTERP_KERNEL::NORM_POLYHED:
6289           {
6290             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6291               {
6292                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6293                 ret->pushBackSilent(i);
6294               }
6295             break;
6296           }
6297         default:
6298           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 !");
6299       }
6300     }
6301   updateTime();
6302   return ret.retn();
6303 }
6304
6305 /*!
6306  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6307  * If it is not the case an exception will be thrown.
6308  * This method is fast because the first cell of \a this is used to compute the plane.
6309  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6310  * \param pos output of size at least 3 used to store a point owned of searched plane.
6311  */
6312 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6313 {
6314   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6315     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6316   const int *conn=_nodal_connec->getConstPointer();
6317   const int *connI=_nodal_connec_index->getConstPointer();
6318   const double *coordsPtr=_coords->getConstPointer();
6319   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6320   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6321 }
6322
6323 /*!
6324  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6325  * cells. Currently cells of the following types are treated:
6326  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6327  * For a cell of other type an exception is thrown.
6328  * Space dimension of a 2D mesh can be either 2 or 3.
6329  * The Edge Ratio of a cell \f$t\f$ is: 
6330  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6331  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6332  *  the smallest edge lengths of \f$t\f$.
6333  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6334  *          cells and one time, lying on \a this mesh. The caller is to delete this
6335  *          field using decrRef() as it is no more needed. 
6336  *  \throw If the coordinates array is not set.
6337  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6338  *  \throw If the connectivity data array has more than one component.
6339  *  \throw If the connectivity data array has a named component.
6340  *  \throw If the connectivity index data array has more than one component.
6341  *  \throw If the connectivity index data array has a named component.
6342  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6343  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6344  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6345  */
6346 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6347 {
6348   checkCoherency();
6349   int spaceDim=getSpaceDimension();
6350   int meshDim=getMeshDimension();
6351   if(spaceDim!=2 && spaceDim!=3)
6352     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6353   if(meshDim!=2 && meshDim!=3)
6354     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6355   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6356   ret->setMesh(this);
6357   int nbOfCells=getNumberOfCells();
6358   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6359   arr->alloc(nbOfCells,1);
6360   double *pt=arr->getPointer();
6361   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6362   const int *conn=_nodal_connec->getConstPointer();
6363   const int *connI=_nodal_connec_index->getConstPointer();
6364   const double *coo=_coords->getConstPointer();
6365   double tmp[12];
6366   for(int i=0;i<nbOfCells;i++,pt++)
6367     {
6368       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6369       switch(t)
6370       {
6371         case INTERP_KERNEL::NORM_TRI3:
6372           {
6373             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6374             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6375             break;
6376           }
6377         case INTERP_KERNEL::NORM_QUAD4:
6378           {
6379             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6380             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6381             break;
6382           }
6383         case INTERP_KERNEL::NORM_TETRA4:
6384           {
6385             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6386             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6387             break;
6388           }
6389         default:
6390           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6391       }
6392       conn+=connI[i+1]-connI[i];
6393     }
6394   ret->setName("EdgeRatio");
6395   ret->synchronizeTimeWithSupport();
6396   return ret.retn();
6397 }
6398
6399 /*!
6400  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6401  * cells. Currently cells of the following types are treated:
6402  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6403  * For a cell of other type an exception is thrown.
6404  * Space dimension of a 2D mesh can be either 2 or 3.
6405  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6406  *          cells and one time, lying on \a this mesh. The caller is to delete this
6407  *          field using decrRef() as it is no more needed. 
6408  *  \throw If the coordinates array is not set.
6409  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6410  *  \throw If the connectivity data array has more than one component.
6411  *  \throw If the connectivity data array has a named component.
6412  *  \throw If the connectivity index data array has more than one component.
6413  *  \throw If the connectivity index data array has a named component.
6414  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6415  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6416  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6417  */
6418 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6419 {
6420   checkCoherency();
6421   int spaceDim=getSpaceDimension();
6422   int meshDim=getMeshDimension();
6423   if(spaceDim!=2 && spaceDim!=3)
6424     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6425   if(meshDim!=2 && meshDim!=3)
6426     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6427   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6428   ret->setMesh(this);
6429   int nbOfCells=getNumberOfCells();
6430   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6431   arr->alloc(nbOfCells,1);
6432   double *pt=arr->getPointer();
6433   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6434   const int *conn=_nodal_connec->getConstPointer();
6435   const int *connI=_nodal_connec_index->getConstPointer();
6436   const double *coo=_coords->getConstPointer();
6437   double tmp[12];
6438   for(int i=0;i<nbOfCells;i++,pt++)
6439     {
6440       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6441       switch(t)
6442       {
6443         case INTERP_KERNEL::NORM_TRI3:
6444           {
6445             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6446             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6447             break;
6448           }
6449         case INTERP_KERNEL::NORM_QUAD4:
6450           {
6451             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6452             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6453             break;
6454           }
6455         case INTERP_KERNEL::NORM_TETRA4:
6456           {
6457             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6458             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6459             break;
6460           }
6461         default:
6462           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6463       }
6464       conn+=connI[i+1]-connI[i];
6465     }
6466   ret->setName("AspectRatio");
6467   ret->synchronizeTimeWithSupport();
6468   return ret.retn();
6469 }
6470
6471 /*!
6472  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6473  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6474  * treated: INTERP_KERNEL::NORM_QUAD4.
6475  * For a cell of other type an exception is thrown.
6476  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6477  *          cells and one time, lying on \a this mesh. The caller is to delete this
6478  *          field using decrRef() as it is no more needed. 
6479  *  \throw If the coordinates array is not set.
6480  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6481  *  \throw If the connectivity data array has more than one component.
6482  *  \throw If the connectivity data array has a named component.
6483  *  \throw If the connectivity index data array has more than one component.
6484  *  \throw If the connectivity index data array has a named component.
6485  *  \throw If \a this->getMeshDimension() != 2.
6486  *  \throw If \a this->getSpaceDimension() != 3.
6487  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6488  */
6489 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6490 {
6491   checkCoherency();
6492   int spaceDim=getSpaceDimension();
6493   int meshDim=getMeshDimension();
6494   if(spaceDim!=3)
6495     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6496   if(meshDim!=2)
6497     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6498   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6499   ret->setMesh(this);
6500   int nbOfCells=getNumberOfCells();
6501   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6502   arr->alloc(nbOfCells,1);
6503   double *pt=arr->getPointer();
6504   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6505   const int *conn=_nodal_connec->getConstPointer();
6506   const int *connI=_nodal_connec_index->getConstPointer();
6507   const double *coo=_coords->getConstPointer();
6508   double tmp[12];
6509   for(int i=0;i<nbOfCells;i++,pt++)
6510     {
6511       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6512       switch(t)
6513       {
6514         case INTERP_KERNEL::NORM_QUAD4:
6515           {
6516             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6517             *pt=INTERP_KERNEL::quadWarp(tmp);
6518             break;
6519           }
6520         default:
6521           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6522       }
6523       conn+=connI[i+1]-connI[i];
6524     }
6525   ret->setName("Warp");
6526   ret->synchronizeTimeWithSupport();
6527   return ret.retn();
6528 }
6529
6530
6531 /*!
6532  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6533  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6534  * treated: INTERP_KERNEL::NORM_QUAD4.
6535  * For a cell of other type an exception is thrown.
6536  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6537  *          cells and one time, lying on \a this mesh. The caller is to delete this
6538  *          field using decrRef() as it is no more needed. 
6539  *  \throw If the coordinates array is not set.
6540  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6541  *  \throw If the connectivity data array has more than one component.
6542  *  \throw If the connectivity data array has a named component.
6543  *  \throw If the connectivity index data array has more than one component.
6544  *  \throw If the connectivity index data array has a named component.
6545  *  \throw If \a this->getMeshDimension() != 2.
6546  *  \throw If \a this->getSpaceDimension() != 3.
6547  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6548  */
6549 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6550 {
6551   checkCoherency();
6552   int spaceDim=getSpaceDimension();
6553   int meshDim=getMeshDimension();
6554   if(spaceDim!=3)
6555     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6556   if(meshDim!=2)
6557     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6558   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6559   ret->setMesh(this);
6560   int nbOfCells=getNumberOfCells();
6561   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6562   arr->alloc(nbOfCells,1);
6563   double *pt=arr->getPointer();
6564   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6565   const int *conn=_nodal_connec->getConstPointer();
6566   const int *connI=_nodal_connec_index->getConstPointer();
6567   const double *coo=_coords->getConstPointer();
6568   double tmp[12];
6569   for(int i=0;i<nbOfCells;i++,pt++)
6570     {
6571       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6572       switch(t)
6573       {
6574         case INTERP_KERNEL::NORM_QUAD4:
6575           {
6576             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6577             *pt=INTERP_KERNEL::quadSkew(tmp);
6578             break;
6579           }
6580         default:
6581           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6582       }
6583       conn+=connI[i+1]-connI[i];
6584     }
6585   ret->setName("Skew");
6586   ret->synchronizeTimeWithSupport();
6587   return ret.retn();
6588 }
6589
6590 /*!
6591  * 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.
6592  *
6593  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6594  *
6595  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6596  */
6597 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6598 {
6599   checkCoherency();
6600   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6601   ret->setMesh(this);
6602   std::set<INTERP_KERNEL::NormalizedCellType> types;
6603   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6604   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6605   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6606   arr->alloc(nbCells,1);
6607   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6608     {
6609       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6610       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6611       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6612     }
6613   ret->setArray(arr);
6614   ret->setName("Diameter");
6615   return ret.retn();
6616 }
6617
6618 /*!
6619  * This method aggregate the bbox of each cell and put it into bbox parameter.
6620  * 
6621  * \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)
6622  *                         For all other cases this input parameter is ignored.
6623  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6624  * 
6625  * \throw If \a this is not fully set (coordinates and connectivity).
6626  * \throw If a cell in \a this has no valid nodeId.
6627  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6628  */
6629 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6630 {
6631   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6632   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.
6633     return getBoundingBoxForBBTreeFast();
6634   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6635     {
6636       bool presenceOfQuadratic(false);
6637       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6638         {
6639           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6640           if(cm.isQuadratic())
6641             presenceOfQuadratic=true;
6642         }
6643       if(!presenceOfQuadratic)
6644         return getBoundingBoxForBBTreeFast();
6645       if(mDim==2 && sDim==2)
6646         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6647       else
6648         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6649     }
6650   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) !");
6651 }
6652
6653 /*!
6654  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6655  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6656  * 
6657  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6658  * 
6659  * \throw If \a this is not fully set (coordinates and connectivity).
6660  * \throw If a cell in \a this has no valid nodeId.
6661  */
6662 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6663 {
6664   checkFullyDefined();
6665   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6666   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6667   double *bbox(ret->getPointer());
6668   for(int i=0;i<nbOfCells*spaceDim;i++)
6669     {
6670       bbox[2*i]=std::numeric_limits<double>::max();
6671       bbox[2*i+1]=-std::numeric_limits<double>::max();
6672     }
6673   const double *coordsPtr(_coords->getConstPointer());
6674   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6675   for(int i=0;i<nbOfCells;i++)
6676     {
6677       int offset=connI[i]+1;
6678       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6679       for(int j=0;j<nbOfNodesForCell;j++)
6680         {
6681           int nodeId=conn[offset+j];
6682           if(nodeId>=0 && nodeId<nbOfNodes)
6683             {
6684               for(int k=0;k<spaceDim;k++)
6685                 {
6686                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6687                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6688                 }
6689               kk++;
6690             }
6691         }
6692       if(kk==0)
6693         {
6694           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6695           throw INTERP_KERNEL::Exception(oss.str().c_str());
6696         }
6697     }
6698   return ret.retn();
6699 }
6700
6701 /*!
6702  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6703  * useful for 2D meshes having quadratic cells
6704  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6705  * the two extremities of the arc of circle).
6706  * 
6707  * \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)
6708  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6709  * \throw If \a this is not fully defined.
6710  * \throw If \a this is not a mesh with meshDimension equal to 2.
6711  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6712  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6713  */
6714 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6715 {
6716   checkFullyDefined();
6717   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6718   if(spaceDim!=2 || mDim!=2)
6719     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!");
6720   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6721   double *bbox(ret->getPointer());
6722   const double *coords(_coords->getConstPointer());
6723   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6724   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6725     {
6726       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6727       int sz(connI[1]-connI[0]-1);
6728       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6729       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6730       INTERP_KERNEL::QuadraticPolygon *pol(0);
6731       for(int j=0;j<sz;j++)
6732         {
6733           int nodeId(conn[*connI+1+j]);
6734           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6735         }
6736       if(!cm.isQuadratic())
6737         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6738       else
6739         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6740       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6741       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6742     }
6743   return ret.retn();
6744 }
6745
6746 /*!
6747  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6748  * useful for 2D meshes having quadratic cells
6749  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6750  * the two extremities of the arc of circle).
6751  * 
6752  * \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)
6753  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6754  * \throw If \a this is not fully defined.
6755  * \throw If \a this is not a mesh with meshDimension equal to 1.
6756  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6757  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6758  */
6759 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6760 {
6761   checkFullyDefined();
6762   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6763   if(spaceDim!=2 || mDim!=1)
6764     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!");
6765   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6766   double *bbox(ret->getPointer());
6767   const double *coords(_coords->getConstPointer());
6768   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6769   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6770     {
6771       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6772       int sz(connI[1]-connI[0]-1);
6773       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6774       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6775       INTERP_KERNEL::Edge *edge(0);
6776       for(int j=0;j<sz;j++)
6777         {
6778           int nodeId(conn[*connI+1+j]);
6779           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6780         }
6781       if(!cm.isQuadratic())
6782         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6783       else
6784         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6785       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6786       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6787     }
6788   return ret.retn();
6789 }
6790
6791 /// @cond INTERNAL
6792
6793 namespace ParaMEDMEMImpl
6794 {
6795   class ConnReader
6796   {
6797   public:
6798     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6799     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6800   private:
6801     const int *_conn;
6802     int _val;
6803   };
6804
6805   class ConnReader2
6806   {
6807   public:
6808     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6809     bool operator() (const int& pos) { return _conn[pos]==_val; }
6810   private:
6811     const int *_conn;
6812     int _val;
6813   };
6814 }
6815
6816 /// @endcond
6817
6818 /*!
6819  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6820  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6821  * \a this is composed in cell types.
6822  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6823  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6824  * This parameter is kept only for compatibility with other methode listed above.
6825  */
6826 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6827 {
6828   checkConnectivityFullyDefined();
6829   const int *conn=_nodal_connec->getConstPointer();
6830   const int *connI=_nodal_connec_index->getConstPointer();
6831   const int *work=connI;
6832   int nbOfCells=getNumberOfCells();
6833   std::size_t n=getAllGeoTypes().size();
6834   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6835   std::set<INTERP_KERNEL::NormalizedCellType> types;
6836   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6837     {
6838       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6839       if(types.find(typ)!=types.end())
6840         {
6841           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6842           oss << " is not contiguous !";
6843           throw INTERP_KERNEL::Exception(oss.str().c_str());
6844         }
6845       types.insert(typ);
6846       ret[3*i]=typ;
6847       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6848       ret[3*i+1]=(int)std::distance(work,work2);
6849       work=work2;
6850     }
6851   return ret;
6852 }
6853
6854 /*!
6855  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6856  * only for types cell, type node is not managed.
6857  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6858  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6859  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6860  * If 2 or more same geometric type is in \a code and exception is thrown too.
6861  *
6862  * This method firstly checks
6863  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6864  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6865  * an exception is thrown too.
6866  * 
6867  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6868  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6869  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6870  */
6871 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6872 {
6873   if(code.empty())
6874     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6875   std::size_t sz=code.size();
6876   std::size_t n=sz/3;
6877   if(sz%3!=0)
6878     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6879   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6880   int nb=0;
6881   bool isNoPflUsed=true;
6882   for(std::size_t i=0;i<n;i++)
6883     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6884       {
6885         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6886         nb+=code[3*i+1];
6887         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6888           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6889         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6890       }
6891   if(types.size()!=n)
6892     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6893   if(isNoPflUsed)
6894     {
6895       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6896         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6897       if(types.size()==_types.size())
6898         return 0;
6899     }
6900   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6901   ret->alloc(nb,1);
6902   int *retPtr=ret->getPointer();
6903   const int *connI=_nodal_connec_index->getConstPointer();
6904   const int *conn=_nodal_connec->getConstPointer();
6905   int nbOfCells=getNumberOfCells();
6906   const int *i=connI;
6907   int kk=0;
6908   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6909     {
6910       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6911       int offset=(int)std::distance(connI,i);
6912       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6913       int nbOfCellsOfCurType=(int)std::distance(i,j);
6914       if(code[3*kk+2]==-1)
6915         for(int k=0;k<nbOfCellsOfCurType;k++)
6916           *retPtr++=k+offset;
6917       else
6918         {
6919           int idInIdsPerType=code[3*kk+2];
6920           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6921             {
6922               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6923               if(zePfl)
6924                 {
6925                   zePfl->checkAllocated();
6926                   if(zePfl->getNumberOfComponents()==1)
6927                     {
6928                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6929                         {
6930                           if(*k>=0 && *k<nbOfCellsOfCurType)
6931                             *retPtr=(*k)+offset;
6932                           else
6933                             {
6934                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6935                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6936                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6937                             }
6938                         }
6939                     }
6940                   else
6941                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6942                 }
6943               else
6944                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6945             }
6946           else
6947             {
6948               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6949               oss << " should be in [0," << idsPerType.size() << ") !";
6950               throw INTERP_KERNEL::Exception(oss.str().c_str());
6951             }
6952         }
6953       i=j;
6954     }
6955   return ret.retn();
6956 }
6957
6958 /*!
6959  * This method makes the hypothesis that \a this is sorted by type. If not an exception will be thrown.
6960  * 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.
6961  * 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.
6962  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6963  * 
6964  * \param [in] profile
6965  * \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.
6966  * \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,
6967  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6968  * \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.
6969  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6970  * \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
6971  */
6972 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6973 {
6974   if(!profile)
6975     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6976   if(profile->getNumberOfComponents()!=1)
6977     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6978   checkConnectivityFullyDefined();
6979   const int *conn=_nodal_connec->getConstPointer();
6980   const int *connI=_nodal_connec_index->getConstPointer();
6981   int nbOfCells=getNumberOfCells();
6982   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6983   std::vector<int> typeRangeVals(1);
6984   for(const int *i=connI;i!=connI+nbOfCells;)
6985     {
6986       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6987       if(std::find(types.begin(),types.end(),curType)!=types.end())
6988         {
6989           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6990         }
6991       types.push_back(curType);
6992       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6993       typeRangeVals.push_back((int)std::distance(connI,i));
6994     }
6995   //
6996   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6997   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6998   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6999   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
7000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
7001   //
7002   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
7003   code.resize(3*nbOfCastsFinal);
7004   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
7005   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
7006   for(int i=0;i<nbOfCastsFinal;i++)
7007     {
7008       int castId=castsPresent->getIJ(i,0);
7009       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
7010       idsInPflPerType2.push_back(tmp3);
7011       code[3*i]=(int)types[castId];
7012       code[3*i+1]=tmp3->getNumberOfTuples();
7013       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
7014       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
7015         {
7016           tmp4->copyStringInfoFrom(*profile);
7017           idsPerType2.push_back(tmp4);
7018           code[3*i+2]=(int)idsPerType2.size()-1;
7019         }
7020       else
7021         {
7022           code[3*i+2]=-1;
7023         }
7024     }
7025   std::size_t sz2=idsInPflPerType2.size();
7026   idsInPflPerType.resize(sz2);
7027   for(std::size_t i=0;i<sz2;i++)
7028     {
7029       DataArrayInt *locDa=idsInPflPerType2[i];
7030       locDa->incrRef();
7031       idsInPflPerType[i]=locDa;
7032     }
7033   std::size_t sz=idsPerType2.size();
7034   idsPerType.resize(sz);
7035   for(std::size_t i=0;i<sz;i++)
7036     {
7037       DataArrayInt *locDa=idsPerType2[i];
7038       locDa->incrRef();
7039       idsPerType[i]=locDa;
7040     }
7041 }
7042
7043 /*!
7044  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7045  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7046  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7047  * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as ParaMEDMEM::MEDCouplingUMesh::buildDescendingConnectivity except the content as described after. The returned array specifies the n-1 mesh reordered by type as MEDMEM does. 'nM1LevMeshIds' contains the ids in returned 'meshnM1'. Finally 'meshnM1Old2New' contains numbering old2new that is to say the cell #k in coarse 'nM1LevMesh' will have the number ret[k] in returned mesh 'nM1LevMesh' MEDMEM reordered.
7048  */
7049 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7050 {
7051   checkFullyDefined();
7052   nM1LevMesh->checkFullyDefined();
7053   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7054     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7055   if(_coords!=nM1LevMesh->getCoords())
7056     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7057   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
7058   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
7059   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7060   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7061   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7062   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7063   tmp->setConnectivity(tmp0,tmp1);
7064   tmp->renumberCells(ret0->getConstPointer(),false);
7065   revDesc=tmp->getNodalConnectivity();
7066   revDescIndx=tmp->getNodalConnectivityIndex();
7067   DataArrayInt *ret=0;
7068   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7069     {
7070       int tmp2;
7071       ret->getMaxValue(tmp2);
7072       ret->decrRef();
7073       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7074       throw INTERP_KERNEL::Exception(oss.str().c_str());
7075     }
7076   nM1LevMeshIds=ret;
7077   //
7078   revDesc->incrRef();
7079   revDescIndx->incrRef();
7080   ret1->incrRef();
7081   ret0->incrRef();
7082   meshnM1Old2New=ret0;
7083   return ret1;
7084 }
7085
7086 /*!
7087  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7088  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7089  * in "Old to New" mode.
7090  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7091  *          this array using decrRef() as it is no more needed.
7092  *  \throw If the nodal connectivity of cells is not defined.
7093  */
7094 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7095 {
7096   checkConnectivityFullyDefined();
7097   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7098   renumberCells(ret->getConstPointer(),false);
7099   return ret.retn();
7100 }
7101
7102 /*!
7103  * This methods checks that cells are sorted by their types.
7104  * This method makes asumption (no check) that connectivity is correctly set before calling.
7105  */
7106 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7107 {
7108   checkFullyDefined();
7109   const int *conn=_nodal_connec->getConstPointer();
7110   const int *connI=_nodal_connec_index->getConstPointer();
7111   int nbOfCells=getNumberOfCells();
7112   std::set<INTERP_KERNEL::NormalizedCellType> types;
7113   for(const int *i=connI;i!=connI+nbOfCells;)
7114     {
7115       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7116       if(types.find(curType)!=types.end())
7117         return false;
7118       types.insert(curType);
7119       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7120     }
7121   return true;
7122 }
7123
7124 /*!
7125  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7126  * The geometric type order is specified by MED file.
7127  * 
7128  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7129  */
7130 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7131 {
7132   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7133 }
7134
7135 /*!
7136  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7137  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7138  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7139  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7140  */
7141 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7142 {
7143   checkFullyDefined();
7144   const int *conn=_nodal_connec->getConstPointer();
7145   const int *connI=_nodal_connec_index->getConstPointer();
7146   int nbOfCells=getNumberOfCells();
7147   if(nbOfCells==0)
7148     return true;
7149   int lastPos=-1;
7150   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7151   for(const int *i=connI;i!=connI+nbOfCells;)
7152     {
7153       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7154       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7155       if(isTypeExists!=orderEnd)
7156         {
7157           int pos=(int)std::distance(orderBg,isTypeExists);
7158           if(pos<=lastPos)
7159             return false;
7160           lastPos=pos;
7161           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7162         }
7163       else
7164         {
7165           if(sg.find(curType)==sg.end())
7166             {
7167               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7168               sg.insert(curType);
7169             }
7170           else
7171             return false;
7172         }
7173     }
7174   return true;
7175 }
7176
7177 /*!
7178  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7179  * 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
7180  * number of tuples than input type array and with one component. This 2nd output array gives type by type the number of occurence of type in 'this'.
7181  */
7182 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7183 {
7184   checkConnectivityFullyDefined();
7185   int nbOfCells=getNumberOfCells();
7186   const int *conn=_nodal_connec->getConstPointer();
7187   const int *connI=_nodal_connec_index->getConstPointer();
7188   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7189   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7190   tmpa->alloc(nbOfCells,1);
7191   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7192   tmpb->fillWithZero();
7193   int *tmp=tmpa->getPointer();
7194   int *tmp2=tmpb->getPointer();
7195   for(const int *i=connI;i!=connI+nbOfCells;i++)
7196     {
7197       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7198       if(where!=orderEnd)
7199         {
7200           int pos=(int)std::distance(orderBg,where);
7201           tmp2[pos]++;
7202           tmp[std::distance(connI,i)]=pos;
7203         }
7204       else
7205         {
7206           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7207           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7208           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7209           throw INTERP_KERNEL::Exception(oss.str().c_str());
7210         }
7211     }
7212   nbPerType=tmpb.retn();
7213   return tmpa.retn();
7214 }
7215
7216 /*!
7217  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7218  *
7219  * \return a new object containing the old to new correspondance.
7220  *
7221  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7222  */
7223 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7224 {
7225   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7226 }
7227
7228 /*!
7229  * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specfied by [ \a orderBg , \a orderEnd ) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in \a this.
7230  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7231  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7232  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7233  */
7234 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7235 {
7236   DataArrayInt *nbPerType=0;
7237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7238   nbPerType->decrRef();
7239   return tmpa->buildPermArrPerLevel();
7240 }
7241
7242 /*!
7243  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7244  * The number of cells remains unchanged after the call of this method.
7245  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7246  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7247  *
7248  * \return the array giving the correspondance old to new.
7249  */
7250 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7251 {
7252   checkFullyDefined();
7253   computeTypes();
7254   const int *conn=_nodal_connec->getConstPointer();
7255   const int *connI=_nodal_connec_index->getConstPointer();
7256   int nbOfCells=getNumberOfCells();
7257   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7258   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7259     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7260       {
7261         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7262         types.push_back(curType);
7263         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7264       }
7265   DataArrayInt *ret=DataArrayInt::New();
7266   ret->alloc(nbOfCells,1);
7267   int *retPtr=ret->getPointer();
7268   std::fill(retPtr,retPtr+nbOfCells,-1);
7269   int newCellId=0;
7270   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7271     {
7272       for(const int *i=connI;i!=connI+nbOfCells;i++)
7273         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7274           retPtr[std::distance(connI,i)]=newCellId++;
7275     }
7276   renumberCells(retPtr,false);
7277   return ret;
7278 }
7279
7280 /*!
7281  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7282  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7283  * This method makes asumption that connectivity is correctly set before calling.
7284  */
7285 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7286 {
7287   checkConnectivityFullyDefined();
7288   const int *conn=_nodal_connec->getConstPointer();
7289   const int *connI=_nodal_connec_index->getConstPointer();
7290   int nbOfCells=getNumberOfCells();
7291   std::vector<MEDCouplingUMesh *> ret;
7292   for(const int *i=connI;i!=connI+nbOfCells;)
7293     {
7294       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7295       int beginCellId=(int)std::distance(connI,i);
7296       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7297       int endCellId=(int)std::distance(connI,i);
7298       int sz=endCellId-beginCellId;
7299       int *cells=new int[sz];
7300       for(int j=0;j<sz;j++)
7301         cells[j]=beginCellId+j;
7302       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7303       delete [] cells;
7304       ret.push_back(m);
7305     }
7306   return ret;
7307 }
7308
7309 /*!
7310  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7311  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7312  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7313  *
7314  * \return a newly allocated instance, that the caller must manage.
7315  * \throw If \a this contains more than one geometric type.
7316  * \throw If the nodal connectivity of \a this is not fully defined.
7317  * \throw If the internal data is not coherent.
7318  */
7319 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7320 {
7321   checkConnectivityFullyDefined();
7322   if(_types.size()!=1)
7323     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7324   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7325   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7326   ret->setCoords(getCoords());
7327   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7328   if(retC)
7329     {
7330       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7331       retC->setNodalConnectivity(c);
7332     }
7333   else
7334     {
7335       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7336       if(!retD)
7337         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7338       DataArrayInt *c=0,*ci=0;
7339       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7340       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7341       retD->setNodalConnectivity(cs,cis);
7342     }
7343   return ret.retn();
7344 }
7345
7346 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7347 {
7348   checkConnectivityFullyDefined();
7349   if(_types.size()!=1)
7350     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7351   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7352   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7353   if(cm.isDynamic())
7354     {
7355       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7356       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7357       throw INTERP_KERNEL::Exception(oss.str().c_str());
7358     }
7359   int nbCells=getNumberOfCells();
7360   int typi=(int)typ;
7361   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7362   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7363   int *outPtr=connOut->getPointer();
7364   const int *conn=_nodal_connec->begin();
7365   const int *connI=_nodal_connec_index->begin();
7366   nbNodesPerCell++;
7367   for(int i=0;i<nbCells;i++,connI++)
7368     {
7369       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7370         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7371       else
7372         {
7373           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 << ") !";
7374           throw INTERP_KERNEL::Exception(oss.str().c_str());
7375         }
7376     }
7377   return connOut.retn();
7378 }
7379
7380 /*!
7381  * Convert the nodal connectivity of the mesh so that all the cells are of dynamic types (polygon or quadratic
7382  * polygon). This returns the corresponding new nodal connectivity in \ref numbering-indirect format.
7383  * \param nodalConn
7384  * \param nodalConnI
7385  */
7386 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7387 {
7388   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7389   checkConnectivityFullyDefined();
7390   if(_types.size()!=1)
7391     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7392   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7393   if(lgth<nbCells)
7394     throw INTERP_KERNEL::Exception(msg0);
7395   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7396   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7397   int *cp(c->getPointer()),*cip(ci->getPointer());
7398   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7399   cip[0]=0;
7400   for(int i=0;i<nbCells;i++,cip++,incip++)
7401     {
7402       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7403       int delta(stop-strt);
7404       if(delta>=1)
7405         {
7406           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7407             cp=std::copy(incp+strt,incp+stop,cp);
7408           else
7409             throw INTERP_KERNEL::Exception(msg0);
7410         }
7411       else
7412         throw INTERP_KERNEL::Exception(msg0);
7413       cip[1]=cip[0]+delta;
7414     }
7415   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7416 }
7417
7418 /*!
7419  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7420  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7421  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7422  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7423  * are not used here to avoid the build of big permutation array.
7424  *
7425  * \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
7426  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7427  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7428  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7429  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7430  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7431  * \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
7432  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7433  */
7434 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7435                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7436                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7437 {
7438   std::vector<const MEDCouplingUMesh *> ms2;
7439   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7440     if(*it)
7441       {
7442         (*it)->checkConnectivityFullyDefined();
7443         ms2.push_back(*it);
7444       }
7445   if(ms2.empty())
7446     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7447   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7448   int meshDim=ms2[0]->getMeshDimension();
7449   std::vector<const MEDCouplingUMesh *> m1ssm;
7450   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7451   //
7452   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7453   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7454   int fake=0,rk=0;
7455   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7456   ret1->alloc(0,1); ret2->alloc(0,1);
7457   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7458     {
7459       if(meshDim!=(*it)->getMeshDimension())
7460         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7461       if(refCoo!=(*it)->getCoords())
7462         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7463       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7464       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7465       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7466       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7467         {
7468           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7469           m1ssmSingleAuto.push_back(singleCell);
7470           m1ssmSingle.push_back(singleCell);
7471           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7472         }
7473     }
7474   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7475   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7476   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7477   for(std::size_t i=0;i<m1ssm.size();i++)
7478     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7479   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7480   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7481   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7482   return ret0.retn();
7483 }
7484
7485 /*!
7486  * This method returns a newly created DataArrayInt instance.
7487  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7488  */
7489 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7490 {
7491   checkFullyDefined();
7492   const int *conn=_nodal_connec->getConstPointer();
7493   const int *connIndex=_nodal_connec_index->getConstPointer();
7494   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7495   for(const int *w=begin;w!=end;w++)
7496     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7497       ret->pushBackSilent(*w);
7498   return ret.retn();
7499 }
7500
7501 /*!
7502  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7503  * are in [0:getNumberOfCells())
7504  */
7505 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7506 {
7507   checkFullyDefined();
7508   const int *conn=_nodal_connec->getConstPointer();
7509   const int *connI=_nodal_connec_index->getConstPointer();
7510   int nbOfCells=getNumberOfCells();
7511   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7512   int *tmp=new int[nbOfCells];
7513   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7514     {
7515       int j=0;
7516       for(const int *i=connI;i!=connI+nbOfCells;i++)
7517         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7518           tmp[std::distance(connI,i)]=j++;
7519     }
7520   DataArrayInt *ret=DataArrayInt::New();
7521   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7522   ret->copyStringInfoFrom(*da);
7523   int *retPtr=ret->getPointer();
7524   const int *daPtr=da->getConstPointer();
7525   int nbOfElems=da->getNbOfElems();
7526   for(int k=0;k<nbOfElems;k++)
7527     retPtr[k]=tmp[daPtr[k]];
7528   delete [] tmp;
7529   return ret;
7530 }
7531
7532 /*!
7533  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7534  * This method \b works \b for mesh sorted by type.
7535  * cells whose ids is in 'idsPerGeoType' array.
7536  * This method conserves coords and name of mesh.
7537  */
7538 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7539 {
7540   std::vector<int> code=getDistributionOfTypes();
7541   std::size_t nOfTypesInThis=code.size()/3;
7542   int sz=0,szOfType=0;
7543   for(std::size_t i=0;i<nOfTypesInThis;i++)
7544     {
7545       if(code[3*i]!=type)
7546         sz+=code[3*i+1];
7547       else
7548         szOfType=code[3*i+1];
7549     }
7550   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7551     if(*work<0 || *work>=szOfType)
7552       {
7553         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7554         oss << ". It should be in [0," << szOfType << ") !";
7555         throw INTERP_KERNEL::Exception(oss.str().c_str());
7556       }
7557   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7558   int *idsPtr=idsTokeep->getPointer();
7559   int offset=0;
7560   for(std::size_t i=0;i<nOfTypesInThis;i++)
7561     {
7562       if(code[3*i]!=type)
7563         for(int j=0;j<code[3*i+1];j++)
7564           *idsPtr++=offset+j;
7565       else
7566         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7567       offset+=code[3*i+1];
7568     }
7569   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7570   ret->copyTinyInfoFrom(this);
7571   return ret.retn();
7572 }
7573
7574 /*!
7575  * This method returns a vector of size 'this->getNumberOfCells()'.
7576  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7577  */
7578 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7579 {
7580   int ncell=getNumberOfCells();
7581   std::vector<bool> ret(ncell);
7582   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7583   const int *c=getNodalConnectivity()->getConstPointer();
7584   for(int i=0;i<ncell;i++)
7585     {
7586       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7587       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7588       ret[i]=cm.isQuadratic();
7589     }
7590   return ret;
7591 }
7592
7593 /*!
7594  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7595  */
7596 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7597 {
7598   if(other->getType()!=UNSTRUCTURED)
7599     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7600   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7601   return MergeUMeshes(this,otherC);
7602 }
7603
7604 /*!
7605  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7606  * computed by averaging coordinates of cell nodes, so this method is not a right
7607  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7608  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7609  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7610  *          components. The caller is to delete this array using decrRef() as it is
7611  *          no more needed.
7612  *  \throw If the coordinates array is not set.
7613  *  \throw If the nodal connectivity of cells is not defined.
7614  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7615  */
7616 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7617 {
7618   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7619   int spaceDim=getSpaceDimension();
7620   int nbOfCells=getNumberOfCells();
7621   ret->alloc(nbOfCells,spaceDim);
7622   ret->copyStringInfoFrom(*getCoords());
7623   double *ptToFill=ret->getPointer();
7624   const int *nodal=_nodal_connec->getConstPointer();
7625   const int *nodalI=_nodal_connec_index->getConstPointer();
7626   const double *coor=_coords->getConstPointer();
7627   for(int i=0;i<nbOfCells;i++)
7628     {
7629       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7630       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7631       ptToFill+=spaceDim;
7632     }
7633   return ret.retn();
7634 }
7635
7636 /*!
7637  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7638  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7639  * 
7640  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7641  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7642  * 
7643  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7644  * \throw If \a this is not fully defined (coordinates and connectivity)
7645  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7646  */
7647 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7648 {
7649   checkFullyDefined();
7650   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7651   int spaceDim=getSpaceDimension();
7652   int nbOfCells=getNumberOfCells();
7653   int nbOfNodes=getNumberOfNodes();
7654   ret->alloc(nbOfCells,spaceDim);
7655   double *ptToFill=ret->getPointer();
7656   const int *nodal=_nodal_connec->getConstPointer();
7657   const int *nodalI=_nodal_connec_index->getConstPointer();
7658   const double *coor=_coords->getConstPointer();
7659   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7660     {
7661       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7662       std::fill(ptToFill,ptToFill+spaceDim,0.);
7663       if(type!=INTERP_KERNEL::NORM_POLYHED)
7664         {
7665           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7666             {
7667               if(*conn>=0 && *conn<nbOfNodes)
7668                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7669               else
7670                 {
7671                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7672                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7673                 }
7674             }
7675           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7676           if(nbOfNodesInCell>0)
7677             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7678           else
7679             {
7680               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7681               throw INTERP_KERNEL::Exception(oss.str().c_str());
7682             }
7683         }
7684       else
7685         {
7686           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7687           s.erase(-1);
7688           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7689             {
7690               if(*it>=0 && *it<nbOfNodes)
7691                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7692               else
7693                 {
7694                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7695                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7696                 }
7697             }
7698           if(!s.empty())
7699             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7700           else
7701             {
7702               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7703               throw INTERP_KERNEL::Exception(oss.str().c_str());
7704             }
7705         }
7706     }
7707   return ret.retn();
7708 }
7709
7710 /*!
7711  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7712  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7713  * are specified via an array of cell ids. 
7714  *  \warning Validity of the specified cell ids is not checked! 
7715  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7716  *  \param [in] begin - an array of cell ids of interest.
7717  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7718  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7719  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7720  *          caller is to delete this array using decrRef() as it is no more needed. 
7721  *  \throw If the coordinates array is not set.
7722  *  \throw If the nodal connectivity of cells is not defined.
7723  *
7724  *  \if ENABLE_EXAMPLES
7725  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7726  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7727  *  \endif
7728  */
7729 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7730 {
7731   DataArrayDouble *ret=DataArrayDouble::New();
7732   int spaceDim=getSpaceDimension();
7733   int nbOfTuple=(int)std::distance(begin,end);
7734   ret->alloc(nbOfTuple,spaceDim);
7735   double *ptToFill=ret->getPointer();
7736   double *tmp=new double[spaceDim];
7737   const int *nodal=_nodal_connec->getConstPointer();
7738   const int *nodalI=_nodal_connec_index->getConstPointer();
7739   const double *coor=_coords->getConstPointer();
7740   for(const int *w=begin;w!=end;w++)
7741     {
7742       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7743       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7744       ptToFill+=spaceDim;
7745     }
7746   delete [] tmp;
7747   return ret;
7748 }
7749
7750 /*!
7751  * 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".
7752  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7753  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7754  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7755  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7756  * 
7757  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7758  * \throw If spaceDim!=3 or meshDim!=2.
7759  * \throw If connectivity of \a this is invalid.
7760  * \throw If connectivity of a cell in \a this points to an invalid node.
7761  */
7762 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7763 {
7764   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7765   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7766   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7767     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7768   ret->alloc(nbOfCells,4);
7769   double *retPtr(ret->getPointer());
7770   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7771   const double *coor(_coords->begin());
7772   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7773     {
7774       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7775       if(nodalI[1]-nodalI[0]>=3)
7776         {
7777           for(int j=0;j<3;j++)
7778             {
7779               int nodeId(nodal[nodalI[0]+1+j]);
7780               if(nodeId>=0 && nodeId<nbOfNodes)
7781                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7782               else
7783                 {
7784                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7785                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7786                 }
7787             }
7788         }
7789       else
7790         {
7791           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7792           throw INTERP_KERNEL::Exception(oss.str().c_str());
7793         }
7794       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7795       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7796     }
7797   return ret.retn();
7798 }
7799
7800 /*!
7801  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7802  * 
7803  */
7804 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7805 {
7806   if(!da)
7807     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7808   da->checkAllocated();
7809   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7810   ret->setCoords(da);
7811   int nbOfTuples=da->getNumberOfTuples();
7812   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7813   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7814   c->alloc(2*nbOfTuples,1);
7815   cI->alloc(nbOfTuples+1,1);
7816   int *cp=c->getPointer();
7817   int *cip=cI->getPointer();
7818   *cip++=0;
7819   for(int i=0;i<nbOfTuples;i++)
7820     {
7821       *cp++=INTERP_KERNEL::NORM_POINT1;
7822       *cp++=i;
7823       *cip++=2*(i+1);
7824     }
7825   ret->setConnectivity(c,cI,true);
7826   return ret.retn();
7827 }
7828 /*!
7829  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7830  * Cells and nodes of
7831  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7832  *  \param [in] mesh1 - the first mesh.
7833  *  \param [in] mesh2 - the second mesh.
7834  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7835  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7836  *          is no more needed.
7837  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7838  *  \throw If the coordinates array is not set in none of the meshes.
7839  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7840  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7841  */
7842 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7843 {
7844   std::vector<const MEDCouplingUMesh *> tmp(2);
7845   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7846   return MergeUMeshes(tmp);
7847 }
7848
7849 /*!
7850  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7851  * Cells and nodes of
7852  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7853  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7854  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7855  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7856  *          is no more needed.
7857  *  \throw If \a a.size() == 0.
7858  *  \throw If \a a[ *i* ] == NULL.
7859  *  \throw If the coordinates array is not set in none of the meshes.
7860  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7861  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7862  */
7863 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7864 {
7865   std::size_t sz=a.size();
7866   if(sz==0)
7867     return MergeUMeshesLL(a);
7868   for(std::size_t ii=0;ii<sz;ii++)
7869     if(!a[ii])
7870       {
7871         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7872         throw INTERP_KERNEL::Exception(oss.str().c_str());
7873       }
7874   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7875   std::vector< const MEDCouplingUMesh * > aa(sz);
7876   int spaceDim=-3;
7877   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7878     {
7879       const MEDCouplingUMesh *cur=a[i];
7880       const DataArrayDouble *coo=cur->getCoords();
7881       if(coo)
7882         spaceDim=coo->getNumberOfComponents();
7883     }
7884   if(spaceDim==-3)
7885     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7886   for(std::size_t i=0;i<sz;i++)
7887     {
7888       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7889       aa[i]=bb[i];
7890     }
7891   return MergeUMeshesLL(aa);
7892 }
7893
7894 /// @cond INTERNAL
7895
7896 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7897 {
7898   if(a.empty())
7899     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7900   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7901   int meshDim=(*it)->getMeshDimension();
7902   int nbOfCells=(*it)->getNumberOfCells();
7903   int meshLgth=(*it++)->getMeshLength();
7904   for(;it!=a.end();it++)
7905     {
7906       if(meshDim!=(*it)->getMeshDimension())
7907         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7908       nbOfCells+=(*it)->getNumberOfCells();
7909       meshLgth+=(*it)->getMeshLength();
7910     }
7911   std::vector<const MEDCouplingPointSet *> aps(a.size());
7912   std::copy(a.begin(),a.end(),aps.begin());
7913   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7914   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7915   ret->setCoords(pts);
7916   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7917   c->alloc(meshLgth,1);
7918   int *cPtr=c->getPointer();
7919   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7920   cI->alloc(nbOfCells+1,1);
7921   int *cIPtr=cI->getPointer();
7922   *cIPtr++=0;
7923   int offset=0;
7924   int offset2=0;
7925   for(it=a.begin();it!=a.end();it++)
7926     {
7927       int curNbOfCell=(*it)->getNumberOfCells();
7928       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7929       const int *curC=(*it)->_nodal_connec->getConstPointer();
7930       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7931       for(int j=0;j<curNbOfCell;j++)
7932         {
7933           const int *src=curC+curCI[j];
7934           *cPtr++=*src++;
7935           for(;src!=curC+curCI[j+1];src++,cPtr++)
7936             {
7937               if(*src!=-1)
7938                 *cPtr=*src+offset2;
7939               else
7940                 *cPtr=-1;
7941             }
7942         }
7943       offset+=curCI[curNbOfCell];
7944       offset2+=(*it)->getNumberOfNodes();
7945     }
7946   //
7947   ret->setConnectivity(c,cI,true);
7948   return ret.retn();
7949 }
7950
7951 /// @endcond
7952
7953 /*!
7954  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7955  * dimension and sharing the node coordinates array.
7956  * All cells of the first mesh precede all cells of the second mesh
7957  * within the result mesh. 
7958  *  \param [in] mesh1 - the first mesh.
7959  *  \param [in] mesh2 - the second mesh.
7960  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7961  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7962  *          is no more needed.
7963  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7964  *  \throw If the meshes do not share the node coordinates array.
7965  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7966  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7967  */
7968 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7969 {
7970   std::vector<const MEDCouplingUMesh *> tmp(2);
7971   tmp[0]=mesh1; tmp[1]=mesh2;
7972   return MergeUMeshesOnSameCoords(tmp);
7973 }
7974
7975 /*!
7976  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7977  * dimension and sharing the node coordinates array.
7978  * All cells of the *i*-th mesh precede all cells of the
7979  * (*i*+1)-th mesh within the result mesh.
7980  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7981  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7982  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7983  *          is no more needed.
7984  *  \throw If \a a.size() == 0.
7985  *  \throw If \a a[ *i* ] == NULL.
7986  *  \throw If the meshes do not share the node coordinates array.
7987  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7988  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7989  */
7990 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7991 {
7992   if(meshes.empty())
7993     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7994   for(std::size_t ii=0;ii<meshes.size();ii++)
7995     if(!meshes[ii])
7996       {
7997         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7998         throw INTERP_KERNEL::Exception(oss.str().c_str());
7999       }
8000   const DataArrayDouble *coords=meshes.front()->getCoords();
8001   int meshDim=meshes.front()->getMeshDimension();
8002   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
8003   int meshLgth=0;
8004   int meshIndexLgth=0;
8005   for(;iter!=meshes.end();iter++)
8006     {
8007       if(coords!=(*iter)->getCoords())
8008         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
8009       if(meshDim!=(*iter)->getMeshDimension())
8010         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
8011       meshLgth+=(*iter)->getMeshLength();
8012       meshIndexLgth+=(*iter)->getNumberOfCells();
8013     }
8014   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
8015   nodal->alloc(meshLgth,1);
8016   int *nodalPtr=nodal->getPointer();
8017   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
8018   nodalIndex->alloc(meshIndexLgth+1,1);
8019   int *nodalIndexPtr=nodalIndex->getPointer();
8020   int offset=0;
8021   for(iter=meshes.begin();iter!=meshes.end();iter++)
8022     {
8023       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
8024       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
8025       int nbOfCells=(*iter)->getNumberOfCells();
8026       int meshLgth2=(*iter)->getMeshLength();
8027       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
8028       if(iter!=meshes.begin())
8029         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
8030       else
8031         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
8032       offset+=meshLgth2;
8033     }
8034   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
8035   ret->setName("merge");
8036   ret->setMeshDimension(meshDim);
8037   ret->setConnectivity(nodal,nodalIndex,true);
8038   ret->setCoords(coords);
8039   return ret;
8040 }
8041
8042 /*!
8043  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8044  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8045  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8046  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8047  * New" mode are returned for each input mesh.
8048  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8049  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
8050  *          valid values [0,1,2], see zipConnectivityTraducer().
8051  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8052  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8053  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
8054  *          no more needed.
8055  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8056  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8057  *          is no more needed.
8058  *  \throw If \a meshes.size() == 0.
8059  *  \throw If \a meshes[ *i* ] == NULL.
8060  *  \throw If the meshes do not share the node coordinates array.
8061  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8062  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
8063  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8064  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
8065  */
8066 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8067 {
8068   //All checks are delegated to MergeUMeshesOnSameCoords
8069   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8070   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8071   corr.resize(meshes.size());
8072   std::size_t nbOfMeshes=meshes.size();
8073   int offset=0;
8074   const int *o2nPtr=o2n->getConstPointer();
8075   for(std::size_t i=0;i<nbOfMeshes;i++)
8076     {
8077       DataArrayInt *tmp=DataArrayInt::New();
8078       int curNbOfCells=meshes[i]->getNumberOfCells();
8079       tmp->alloc(curNbOfCells,1);
8080       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8081       offset+=curNbOfCells;
8082       tmp->setName(meshes[i]->getName());
8083       corr[i]=tmp;
8084     }
8085   return ret.retn();
8086 }
8087
8088 /*!
8089  * Makes all given meshes share the nodal connectivity array. The common connectivity
8090  * array is created by concatenating the connectivity arrays of all given meshes. All
8091  * the given meshes must be of the same space dimension but dimension of cells **can
8092  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8093  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8094  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8095  *  \param [in,out] meshes - a vector of meshes to update.
8096  *  \throw If any of \a meshes is NULL.
8097  *  \throw If the coordinates array is not set in any of \a meshes.
8098  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8099  *  \throw If \a meshes are of different space dimension.
8100  */
8101 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8102 {
8103   std::size_t sz=meshes.size();
8104   if(sz==0 || sz==1)
8105     return;
8106   std::vector< const DataArrayDouble * > coords(meshes.size());
8107   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8108   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8109     {
8110       if((*it))
8111         {
8112           (*it)->checkConnectivityFullyDefined();
8113           const DataArrayDouble *coo=(*it)->getCoords();
8114           if(coo)
8115             *it2=coo;
8116           else
8117             {
8118               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8119               oss << " has no coordinate array defined !";
8120               throw INTERP_KERNEL::Exception(oss.str().c_str());
8121             }
8122         }
8123       else
8124         {
8125           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8126           oss << " is null !";
8127           throw INTERP_KERNEL::Exception(oss.str().c_str());
8128         }
8129     }
8130   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8131   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8132   int offset=(*it)->getNumberOfNodes();
8133   (*it++)->setCoords(res);
8134   for(;it!=meshes.end();it++)
8135     {
8136       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8137       (*it)->setCoords(res);
8138       (*it)->shiftNodeNumbersInConn(offset);
8139       offset+=oldNumberOfNodes;
8140     }
8141 }
8142
8143 /*!
8144  * Merges nodes coincident with a given precision within all given meshes that share
8145  * the nodal connectivity array. The given meshes **can be of different** mesh
8146  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8147  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8148  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8149  *  \param [in,out] meshes - a vector of meshes to update.
8150  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8151  *  \throw If any of \a meshes is NULL.
8152  *  \throw If the \a meshes do not share the same node coordinates array.
8153  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8154  */
8155 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8156 {
8157   if(meshes.empty())
8158     return ;
8159   std::set<const DataArrayDouble *> s;
8160   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8161     {
8162       if(*it)
8163         s.insert((*it)->getCoords());
8164       else
8165         {
8166           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 !";
8167           throw INTERP_KERNEL::Exception(oss.str().c_str());
8168         }
8169     }
8170   if(s.size()!=1)
8171     {
8172       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 !";
8173       throw INTERP_KERNEL::Exception(oss.str().c_str());
8174     }
8175   const DataArrayDouble *coo=*(s.begin());
8176   if(!coo)
8177     return;
8178   //
8179   DataArrayInt *comm,*commI;
8180   coo->findCommonTuples(eps,-1,comm,commI);
8181   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8182   int oldNbOfNodes=coo->getNumberOfTuples();
8183   int newNbOfNodes;
8184   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8185   if(oldNbOfNodes==newNbOfNodes)
8186     return ;
8187   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8188   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8189     {
8190       (*it)->renumberNodesInConn(o2n->getConstPointer());
8191       (*it)->setCoords(newCoords);
8192     } 
8193 }
8194
8195 /*!
8196  * This method takes in input a cell defined by its MEDcouplingUMesh connectivity [ \a connBg , \a connEnd ) and returns its extruded cell by inserting the result at the end of ret.
8197  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8198  * \param isQuad specifies the policy of connectivity.
8199  * @ret in/out parameter in which the result will be append
8200  */
8201 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8202 {
8203   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8204   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8205   ret.push_back(cm.getExtrudedType());
8206   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8207   switch(flatType)
8208   {
8209     case INTERP_KERNEL::NORM_POINT1:
8210       {
8211         ret.push_back(connBg[1]);
8212         ret.push_back(connBg[1]+nbOfNodesPerLev);
8213         break;
8214       }
8215     case INTERP_KERNEL::NORM_SEG2:
8216       {
8217         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8218         ret.insert(ret.end(),conn,conn+4);
8219         break;
8220       }
8221     case INTERP_KERNEL::NORM_SEG3:
8222       {
8223         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8224         ret.insert(ret.end(),conn,conn+8);
8225         break;
8226       }
8227     case INTERP_KERNEL::NORM_QUAD4:
8228       {
8229         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8230         ret.insert(ret.end(),conn,conn+8);
8231         break;
8232       }
8233     case INTERP_KERNEL::NORM_TRI3:
8234       {
8235         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8236         ret.insert(ret.end(),conn,conn+6);
8237         break;
8238       }
8239     case INTERP_KERNEL::NORM_TRI6:
8240       {
8241         int conn[15]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4],connBg[5],connBg[6],connBg[4]+deltaz,connBg[5]+deltaz,connBg[6]+deltaz,
8242           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8243         ret.insert(ret.end(),conn,conn+15);
8244         break;
8245       }
8246     case INTERP_KERNEL::NORM_QUAD8:
8247       {
8248         int conn[20]={
8249           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8250           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8251           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8252         };
8253         ret.insert(ret.end(),conn,conn+20);
8254         break;
8255       }
8256     case INTERP_KERNEL::NORM_POLYGON:
8257       {
8258         std::back_insert_iterator< std::vector<int> > ii(ret);
8259         std::copy(connBg+1,connEnd,ii);
8260         *ii++=-1;
8261         std::reverse_iterator<const int *> rConnBg(connEnd);
8262         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8263         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8264         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8265         for(std::size_t i=0;i<nbOfRadFaces;i++)
8266           {
8267             *ii++=-1;
8268             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8269             std::copy(conn,conn+4,ii);
8270           }
8271         break;
8272       }
8273     default:
8274       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8275   }
8276 }
8277
8278 /*!
8279  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8280  */
8281 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8282 {
8283   std::size_t i, ip1;
8284   double v[3]={0.,0.,0.};
8285   std::size_t sz=std::distance(begin,end);
8286   if(isQuadratic)
8287     sz/=2;
8288   for(i=0;i<sz;i++)
8289     {
8290       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];
8291       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8292       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8293     }
8294   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8295
8296   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8297   // SEG3 forming a circle):
8298   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8299     {
8300       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8301       for(std::size_t j=0;j<sz;j++)
8302         {
8303           if (j%2)  // current point i is quadratic, next point i+1 is standard
8304             {
8305               i = sz+j;
8306               ip1 = (j+1)%sz; // ip1 = "i+1"
8307             }
8308           else      // current point i is standard, next point i+1 is quadratic
8309             {
8310               i = j;
8311               ip1 = j+sz;
8312             }
8313           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8314           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8315           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8316         }
8317       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8318     }
8319   return (ret>0.);
8320 }
8321
8322 /*!
8323  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8324  */
8325 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8326 {
8327   std::vector<std::pair<int,int> > edges;
8328   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8329   const int *bgFace=begin;
8330   for(std::size_t i=0;i<nbOfFaces;i++)
8331     {
8332       const int *endFace=std::find(bgFace+1,end,-1);
8333       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8334       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8335         {
8336           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8337           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8338             return false;
8339           edges.push_back(p1);
8340         }
8341       bgFace=endFace+1;
8342     }
8343   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8344 }
8345
8346 /*!
8347  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8348  */
8349 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8350 {
8351   double vec0[3],vec1[3];
8352   std::size_t sz=std::distance(begin,end);
8353   if(sz%2!=0)
8354     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8355   int nbOfNodes=(int)sz/2;
8356   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8357   const double *pt0=coords+3*begin[0];
8358   const double *pt1=coords+3*begin[nbOfNodes];
8359   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8360   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8361 }
8362
8363 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8364 {
8365   std::size_t sz=std::distance(begin,end);
8366   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8367   std::size_t nbOfNodes(sz/2);
8368   std::copy(begin,end,(int *)tmp);
8369   for(std::size_t j=1;j<nbOfNodes;j++)
8370     {
8371       begin[j]=tmp[nbOfNodes-j];
8372       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8373     }
8374 }
8375
8376 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8377 {
8378   std::size_t sz=std::distance(begin,end);
8379   if(sz!=4)
8380     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8381   double vec0[3],vec1[3];
8382   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8383   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]; 
8384   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;
8385 }
8386
8387 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8388 {
8389   std::size_t sz=std::distance(begin,end);
8390   if(sz!=5)
8391     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8392   double vec0[3];
8393   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8394   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8395   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8396 }
8397
8398 /*!
8399  * 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 ) 
8400  * 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
8401  * a 2D space.
8402  *
8403  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8404  * \param [in] coords the coordinates with nb of components exactly equal to 3
8405  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8406  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8407  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8408  */
8409 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8410 {
8411   int nbFaces=std::count(begin+1,end,-1)+1;
8412   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8413   double *vPtr=v->getPointer();
8414   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8415   double *pPtr=p->getPointer();
8416   const int *stFaceConn=begin+1;
8417   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8418     {
8419       const int *endFaceConn=std::find(stFaceConn,end,-1);
8420       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8421       stFaceConn=endFaceConn+1;
8422     }
8423   pPtr=p->getPointer(); vPtr=v->getPointer();
8424   DataArrayInt *comm1=0,*commI1=0;
8425   v->findCommonTuples(eps,-1,comm1,commI1);
8426   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8427   const int *comm1Ptr=comm1->getConstPointer();
8428   const int *commI1Ptr=commI1->getConstPointer();
8429   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8430   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8431   //
8432   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8433   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8434   mm->finishInsertingCells();
8435   //
8436   for(int i=0;i<nbOfGrps1;i++)
8437     {
8438       int vecId=comm1Ptr[commI1Ptr[i]];
8439       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8440       DataArrayInt *comm2=0,*commI2=0;
8441       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8442       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8443       const int *comm2Ptr=comm2->getConstPointer();
8444       const int *commI2Ptr=commI2->getConstPointer();
8445       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8446       for(int j=0;j<nbOfGrps2;j++)
8447         {
8448           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8449             {
8450               res->insertAtTheEnd(begin,end);
8451               res->pushBackSilent(-1);
8452             }
8453           else
8454             {
8455               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8456               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8457               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8458               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8459               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8460               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8461               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8462               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8463               const int *idsNodePtr=idsNode->getConstPointer();
8464               double center[3]; center[0]=pPtr[pointId]*vPtr[3*vecId]; center[1]=pPtr[pointId]*vPtr[3*vecId+1]; center[2]=pPtr[pointId]*vPtr[3*vecId+2];
8465               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8466               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8467               if(std::abs(norm)>eps)
8468                 {
8469                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8470                   mm3->rotate(center,vec,angle);
8471                 }
8472               mm3->changeSpaceDimension(2);
8473               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8474               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8475               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8476               int nbOfCells=mm4->getNumberOfCells();
8477               for(int k=0;k<nbOfCells;k++)
8478                 {
8479                   int l=0;
8480                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8481                     res->pushBackSilent(idsNodePtr[*work]);
8482                   res->pushBackSilent(-1);
8483                 }
8484             }
8485         }
8486     }
8487   res->popBackSilent();
8488 }
8489
8490 /*!
8491  * 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
8492  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8493  * 
8494  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8495  * \param [in] coords coordinates expected to have 3 components.
8496  * \param [in] begin start of the nodal connectivity of the face.
8497  * \param [in] end end of the nodal connectivity (excluded) of the face.
8498  * \param [out] v the normalized vector of size 3
8499  * \param [out] p the pos of plane
8500  */
8501 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8502 {
8503   std::size_t nbPoints=std::distance(begin,end);
8504   if(nbPoints<3)
8505     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8506   double vec[3]={0.,0.,0.};
8507   std::size_t j=0;
8508   bool refFound=false;
8509   for(;j<nbPoints-1 && !refFound;j++)
8510     {
8511       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8512       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8513       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8514       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8515       if(norm>eps)
8516         {
8517           refFound=true;
8518           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8519         }
8520     }
8521   for(std::size_t i=j;i<nbPoints-1;i++)
8522     {
8523       double curVec[3];
8524       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8525       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8526       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8527       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8528       if(norm<eps)
8529         continue;
8530       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8531       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];
8532       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8533       if(norm>eps)
8534         {
8535           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8536           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8537           return ;
8538         }
8539     }
8540   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8541 }
8542
8543 /*!
8544  * This method tries to obtain a well oriented polyhedron.
8545  * If the algorithm fails, an exception will be thrown.
8546  */
8547 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8548 {
8549   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8550   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8551   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8552   isPerm[0]=true;
8553   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8554   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8555   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8556   //
8557   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8558     {
8559       bgFace=begin;
8560       std::size_t smthChanged=0;
8561       for(std::size_t i=0;i<nbOfFaces;i++)
8562         {
8563           endFace=std::find(bgFace+1,end,-1);
8564           nbOfEdgesInFace=std::distance(bgFace,endFace);
8565           if(!isPerm[i])
8566             {
8567               bool b;
8568               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8569                 {
8570                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8571                   std::pair<int,int> p2(p1.second,p1.first);
8572                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8573                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8574                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8575                 }
8576               if(isPerm[i])
8577                 { 
8578                   if(!b)
8579                     std::reverse(bgFace+1,endFace);
8580                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8581                     {
8582                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8583                       std::pair<int,int> p2(p1.second,p1.first);
8584                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8585                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8586                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8587                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8588                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8589                       if(it!=edgesOK.end())
8590                         {
8591                           edgesOK.erase(it);
8592                           edgesFinished.push_back(p1);
8593                         }
8594                       else
8595                         edgesOK.push_back(p1);
8596                     }
8597                 }
8598             }
8599           bgFace=endFace+1;
8600         }
8601       if(smthChanged==0)
8602         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8603     }
8604   if(!edgesOK.empty())
8605     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8606   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8607     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8608       bgFace=begin;
8609       for(std::size_t i=0;i<nbOfFaces;i++)
8610         {
8611           endFace=std::find(bgFace+1,end,-1);
8612           std::reverse(bgFace+1,endFace);
8613           bgFace=endFace+1;
8614         }
8615     }
8616 }
8617
8618 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8619 {
8620   int nbOfNodesExpected(skin->getNumberOfNodes());
8621   const int *n2oPtr(n2o->getConstPointer());
8622   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8623   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8624   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8625   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8626   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8627   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8628   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8629   if(nbOfNodesExpected<1)
8630     return ret.retn();
8631   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8632   *work++=n2oPtr[prevNode];
8633   for(int i=1;i<nbOfNodesExpected;i++)
8634     {
8635       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8636         {
8637           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8638           conn.erase(prevNode);
8639           if(conn.size()==1)
8640             {
8641               int curNode(*(conn.begin()));
8642               *work++=n2oPtr[curNode];
8643               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8644               shar.erase(prevCell);
8645               if(shar.size()==1)
8646                 {
8647                   prevCell=*(shar.begin());
8648                   prevNode=curNode;
8649                 }
8650               else
8651                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8652             }
8653           else
8654             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8655         }
8656       else
8657         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8658     }
8659   return ret.retn();
8660 }
8661
8662 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8663 {
8664   int nbOfNodesExpected(skin->getNumberOfNodes());
8665   int nbOfTurn(nbOfNodesExpected/2);
8666   const int *n2oPtr(n2o->getConstPointer());
8667   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8668   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8669   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8670   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8671   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8672   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8673   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8674   if(nbOfNodesExpected<1)
8675     return ret.retn();
8676   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8677   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8678   for(int i=1;i<nbOfTurn;i++)
8679     {
8680       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8681         {
8682           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8683           conn.erase(prevNode);
8684           if(conn.size()==1)
8685             {
8686               int curNode(*(conn.begin()));
8687               *work=n2oPtr[curNode];
8688               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8689               shar.erase(prevCell);
8690               if(shar.size()==1)
8691                 {
8692                   int curCell(*(shar.begin()));
8693                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8694                   prevCell=curCell;
8695                   prevNode=curNode;
8696                   work++;
8697                 }
8698               else
8699                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8700             }
8701           else
8702             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8703         }
8704       else
8705         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8706     }
8707   return ret.retn();
8708 }
8709
8710 /*!
8711  * This method makes the assumption spacedimension == meshdimension == 2.
8712  * This method works only for linear cells.
8713  * 
8714  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8715  */
8716 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8717 {
8718   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8719     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8720   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8721   int oldNbOfNodes(skin->getNumberOfNodes());
8722   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8723   int nbOfNodesExpected(skin->getNumberOfNodes());
8724   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8725   int nbCells(skin->getNumberOfCells());
8726   if(nbCells==nbOfNodesExpected)
8727     return buildUnionOf2DMeshLinear(skin,n2o);
8728   else if(2*nbCells==nbOfNodesExpected)
8729     return buildUnionOf2DMeshQuadratic(skin,n2o);
8730   else
8731     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8732 }
8733
8734 /*!
8735  * This method makes the assumption spacedimension == meshdimension == 3.
8736  * This method works only for linear cells.
8737  * 
8738  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8739  */
8740 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8741 {
8742   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8743     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8744   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8745   const int *conn=m->getNodalConnectivity()->getConstPointer();
8746   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8747   int nbOfCells=m->getNumberOfCells();
8748   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8749   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8750   if(nbOfCells<1)
8751     return ret.retn();
8752   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8753   for(int i=1;i<nbOfCells;i++)
8754     {
8755       *work++=-1;
8756       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8757     }
8758   return ret.retn();
8759 }
8760
8761 /*!
8762  * \brief Creates a graph of cell neighbors
8763  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8764  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
8765  *  For example
8766  *  - index:  0 3 5 6 6
8767  *  - value:  1 2 3 2 3 3
8768  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8769  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8770  */
8771 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8772 {
8773   checkConnectivityFullyDefined();
8774
8775   int meshDim = this->getMeshDimension();
8776   ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8777   ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8778   this->getReverseNodalConnectivity(revConn,indexr);
8779   const int* indexr_ptr=indexr->getConstPointer();
8780   const int* revConn_ptr=revConn->getConstPointer();
8781
8782   const ParaMEDMEM::DataArrayInt* index;
8783   const ParaMEDMEM::DataArrayInt* conn;
8784   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8785   index=this->getNodalConnectivityIndex();
8786   int nbCells=this->getNumberOfCells();
8787   const int* index_ptr=index->getConstPointer();
8788   const int* conn_ptr=conn->getConstPointer();
8789
8790   //creating graph arcs (cell to cell relations)
8791   //arcs are stored in terms of (index,value) notation
8792   // 0 3 5 6 6
8793   // 1 2 3 2 3 3
8794   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8795   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8796
8797   //warning here one node have less than or equal effective number of cell with it
8798   //but cell could have more than effective nodes
8799   //because other equals nodes in other domain (with other global inode)
8800   std::vector <int> cell2cell_index(nbCells+1,0);
8801   std::vector <int> cell2cell;
8802   cell2cell.reserve(3*nbCells);
8803
8804   for (int icell=0; icell<nbCells;icell++)
8805     {
8806       std::map<int,int > counter;
8807       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8808         {
8809           int inode=conn_ptr[iconn];
8810           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8811             {
8812               int icell2=revConn_ptr[iconnr];
8813               std::map<int,int>::iterator iter=counter.find(icell2);
8814               if (iter!=counter.end()) (iter->second)++;
8815               else counter.insert(std::make_pair(icell2,1));
8816             }
8817         }
8818       for (std::map<int,int>::const_iterator iter=counter.begin();
8819            iter!=counter.end(); iter++)
8820         if (iter->second >= meshDim)
8821           {
8822             cell2cell_index[icell+1]++;
8823             cell2cell.push_back(iter->first);
8824           }
8825     }
8826   indexr->decrRef();
8827   revConn->decrRef();
8828   cell2cell_index[0]=0;
8829   for (int icell=0; icell<nbCells;icell++)
8830     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8831
8832   //filling up index and value to create skylinearray structure
8833   MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8834   return array;
8835 }
8836
8837 /*!
8838  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8839  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8840  */
8841 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8842 {
8843   double *w=zipFrmt;
8844   if(spaceDim==3)
8845     for(int i=0;i<nbOfNodesInCell;i++)
8846       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8847   else if(spaceDim==2)
8848     {
8849       for(int i=0;i<nbOfNodesInCell;i++)
8850         {
8851           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8852           *w++=0.;
8853         }
8854     }
8855   else
8856     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8857 }
8858
8859 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8860 {
8861   int nbOfCells=getNumberOfCells();
8862   if(nbOfCells<=0)
8863     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8864   static const int PARAMEDMEM2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,34,23,28,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,29,-1,-1,25,42,36,4};
8865   ofs << "  <" << getVTKDataSetType() << ">\n";
8866   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8867   ofs << "      <PointData>\n" << pointData << std::endl;
8868   ofs << "      </PointData>\n";
8869   ofs << "      <CellData>\n" << cellData << std::endl;
8870   ofs << "      </CellData>\n";
8871   ofs << "      <Points>\n";
8872   if(getSpaceDimension()==3)
8873     _coords->writeVTK(ofs,8,"Points",byteData);
8874   else
8875     {
8876       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8877       coo->writeVTK(ofs,8,"Points",byteData);
8878     }
8879   ofs << "      </Points>\n";
8880   ofs << "      <Cells>\n";
8881   const int *cPtr=_nodal_connec->getConstPointer();
8882   const int *cIPtr=_nodal_connec_index->getConstPointer();
8883   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8884   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8885   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8886   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8887   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8888   int szFaceOffsets=0,szConn=0;
8889   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8890     {
8891       *w2=cPtr[cIPtr[i]];
8892       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8893         {
8894           *w1=-1;
8895           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8896           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8897         }
8898       else
8899         {
8900           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8901           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8902           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8903           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8904           w4=std::copy(c.begin(),c.end(),w4);
8905         }
8906     }
8907   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8908   types->writeVTK(ofs,8,"UInt8","types",byteData);
8909   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8910   if(szFaceOffsets!=0)
8911     {//presence of Polyhedra
8912       connectivity->reAlloc(szConn);
8913       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8914       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8915       w1=faces->getPointer();
8916       for(int i=0;i<nbOfCells;i++)
8917         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8918           {
8919             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8920             *w1++=nbFaces;
8921             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8922             for(int j=0;j<nbFaces;j++)
8923               {
8924                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8925                 *w1++=(int)std::distance(w6,w5);
8926                 w1=std::copy(w6,w5,w1);
8927                 w6=w5+1;
8928               }
8929           }
8930       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8931     }
8932   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8933   ofs << "      </Cells>\n";
8934   ofs << "    </Piece>\n";
8935   ofs << "  </" << getVTKDataSetType() << ">\n";
8936 }
8937
8938 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8939 {
8940   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8941   if(_mesh_dim==-2)
8942     { stream << " Not set !"; return ; }
8943   stream << " Mesh dimension : " << _mesh_dim << ".";
8944   if(_mesh_dim==-1)
8945     return ;
8946   if(!_coords)
8947     { stream << " No coordinates set !"; return ; }
8948   if(!_coords->isAllocated())
8949     { stream << " Coordinates set but not allocated !"; return ; }
8950   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8951   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8952   if(!_nodal_connec_index)
8953     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8954   if(!_nodal_connec_index->isAllocated())
8955     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8956   int lgth=_nodal_connec_index->getNumberOfTuples();
8957   int cpt=_nodal_connec_index->getNumberOfComponents();
8958   if(cpt!=1 || lgth<1)
8959     return ;
8960   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8961 }
8962
8963 std::string MEDCouplingUMesh::getVTKDataSetType() const
8964 {
8965   return std::string("UnstructuredGrid");
8966 }
8967
8968 std::string MEDCouplingUMesh::getVTKFileExtension() const
8969 {
8970   return std::string("vtu");
8971 }
8972
8973 /*!
8974  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8975  * returns a result mesh constituted by polygons.
8976  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8977  * all nodes from m2.
8978  * The meshes should be in 2D space. In
8979  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8980  * meshes.
8981  *  \param [in] m1 - the first input mesh which is a partitioned object. The mesh must be so that each point in the space covered by \a m1
8982  *                      must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
8983  *  \param [in] m2 - the second input mesh which is a partition tool. The mesh must be so that each point in the space covered by \a m2
8984  *                      must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
8985  *  \param [in] eps - precision used to detect coincident mesh entities.
8986  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8987  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8988  *         this array using decrRef() as it is no more needed.
8989  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8990  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8991  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8992  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8993  *         it is no more needed.  
8994  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8995  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8996  *         is no more needed.  
8997  *  \throw If the coordinates array is not set in any of the meshes.
8998  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8999  *  \throw If any of the meshes is not a 2D mesh in 2D space.
9000  *
9001  *  \sa conformize2D, mergeNodes
9002  */
9003 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9004                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
9005 {
9006   if(!m1 || !m2)
9007     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
9008   m1->checkFullyDefined();
9009   m2->checkFullyDefined();
9010   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
9011     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
9012
9013   // Step 1: compute all edge intersections (new nodes)
9014   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9015   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
9016   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
9017   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9018   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
9019                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
9020                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
9021   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
9022   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
9023   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
9024
9025   // Step 2: re-order newly created nodes according to the ordering found in m2
9026   std::vector< std::vector<int> > intersectEdge2;
9027   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
9028   subDiv2.clear(); dd5=0; dd6=0;
9029
9030   // Step 3:
9031   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
9032   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
9033   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
9034                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
9035
9036   // Step 4: Prepare final result:
9037   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9038   addCooDa->alloc((int)(addCoo.size())/2,2);
9039   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9040   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9041   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9042   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9043   std::vector<const DataArrayDouble *> coordss(4);
9044   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9045   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9046   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9047   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9048   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9049   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9050   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9051   ret->setConnectivity(conn,connI,true);
9052   ret->setCoords(coo);
9053   cellNb1=c1.retn(); cellNb2=c2.retn();
9054   return ret.retn();
9055 }
9056
9057 /// @cond INTERNAL
9058
9059 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9060 {
9061   if(candidates.empty())
9062     return false;
9063   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9064     {
9065       const std::vector<int>& pool(intersectEdge1[*it]);
9066       int tmp[2]; tmp[0]=start; tmp[1]=stop;
9067       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9068         {
9069           retVal=*it+1;
9070           return true;
9071         }
9072       tmp[0]=stop; tmp[1]=start;
9073       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9074         {
9075           retVal=-*it-1;
9076           return true;
9077         }
9078     }
9079   return false;
9080 }
9081
9082 MEDCouplingUMesh *BuildMesh1DCutFrom(const MEDCouplingUMesh *mesh1D, const std::vector< std::vector<int> >& intersectEdge2, const DataArrayDouble *coords1, const std::vector<double>& addCoo, const std::map<int,int>& mergedNodes, const std::vector< std::vector<int> >& colinear2, const std::vector< std::vector<int> >& intersectEdge1,
9083                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9084 {
9085   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9086   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9087   int nCells(mesh1D->getNumberOfCells());
9088   if(nCells!=(int)intersectEdge2.size())
9089     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9090   const DataArrayDouble *coo2(mesh1D->getCoords());
9091   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9092   const double *coo2Ptr(coo2->begin());
9093   int offset1(coords1->getNumberOfTuples());
9094   int offset2(offset1+coo2->getNumberOfTuples());
9095   int offset3(offset2+addCoo.size()/2);
9096   std::vector<double> addCooQuad;
9097   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9098   int tmp[4],cicnt(0),kk(0);
9099   for(int i=0;i<nCells;i++)
9100     {
9101       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9102       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9103       const std::vector<int>& subEdges(intersectEdge2[i]);
9104       int nbSubEdge(subEdges.size()/2);
9105       for(int j=0;j<nbSubEdge;j++,kk++)
9106         {
9107           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> n1(MEDCouplingUMeshBuildQPNode(subEdges[2*j],coords1->begin(),offset1,coo2Ptr,offset2,addCoo)),n2(MEDCouplingUMeshBuildQPNode(subEdges[2*j+1],coords1->begin(),offset1,coo2Ptr,offset2,addCoo));
9108           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9109           INTERP_KERNEL::Edge *e2Ptr(e2);
9110           std::map<int,int>::const_iterator itm;
9111           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9112             {
9113               tmp[0]=INTERP_KERNEL::NORM_SEG3;
9114               itm=mergedNodes.find(subEdges[2*j]);
9115               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9116               itm=mergedNodes.find(subEdges[2*j+1]);
9117               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9118               tmp[3]=offset3+(int)addCooQuad.size()/2;
9119               double tmp2[2];
9120               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9121               cicnt+=4;
9122               cOut->insertAtTheEnd(tmp,tmp+4);
9123               ciOut->pushBackSilent(cicnt);
9124             }
9125           else
9126             {
9127               tmp[0]=INTERP_KERNEL::NORM_SEG2;
9128               itm=mergedNodes.find(subEdges[2*j]);
9129               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9130               itm=mergedNodes.find(subEdges[2*j+1]);
9131               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9132               cicnt+=3;
9133               cOut->insertAtTheEnd(tmp,tmp+3);
9134               ciOut->pushBackSilent(cicnt);
9135             }
9136           int tmp00;
9137           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9138             {
9139               idsInRetColinear->pushBackSilent(kk);
9140               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9141             }
9142         }
9143       e->decrRef();
9144     }
9145   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9146   ret->setConnectivity(cOut,ciOut,true);
9147   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9148   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9149   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9150   std::vector<const DataArrayDouble *> coordss(4);
9151   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9152   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9153   ret->setCoords(arr);
9154   return ret.retn();
9155 }
9156
9157 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9158 {
9159   std::vector<int> allEdges;
9160   for(const int *it2(descBg);it2!=descEnd;it2++)
9161     {
9162       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9163       if(*it2>0)
9164         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9165       else
9166         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9167     }
9168   std::size_t nb(allEdges.size());
9169   if(nb%2!=0)
9170     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9171   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9172   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9173   ret->setCoords(coords);
9174   ret->allocateCells(1);
9175   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9176   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9177     connOut[kk]=allEdges[2*kk];
9178   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9179   return ret.retn();
9180 }
9181
9182 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9183 {
9184   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9185   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9186   std::size_t ii(0);
9187   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9188   if(sz!=std::distance(descBg,descEnd))
9189     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9190   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9191   std::vector<int> allEdges,centers;
9192   const double *coordsPtr(coords->begin());
9193   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9194   int offset(coords->getNumberOfTuples());
9195   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9196     {
9197       INTERP_KERNEL::NormalizedCellType typeOfSon;
9198       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9199       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9200       if(*it2>0)
9201         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9202       else
9203         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9204       if(edge1.size()==2)
9205         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9206       else
9207         {//the current edge has been subsplit -> create corresponding centers.
9208           std::size_t nbOfCentersToAppend(edge1.size()/2);
9209           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9210           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9211           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9212           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9213             {
9214               double tmpp[2];
9215               const double *aa(coordsPtr+2*(*it3++));
9216               const double *bb(coordsPtr+2*(*it3++));
9217               ee->getMiddleOfPoints(aa,bb,tmpp);
9218               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9219               centers.push_back(offset+k);
9220             }
9221         }
9222     }
9223   std::size_t nb(allEdges.size());
9224   if(nb%2!=0)
9225     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9226   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9227   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9228   if(addCoo->empty())
9229     ret->setCoords(coords);
9230   else
9231     {
9232       addCoo->rearrange(2);
9233       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9234       ret->setCoords(addCoo);
9235     }
9236   ret->allocateCells(1);
9237   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9238   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9239     connOut[kk]=allEdges[2*kk];
9240   connOut.insert(connOut.end(),centers.begin(),centers.end());
9241   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9242   return ret.retn();
9243 }
9244
9245 /*!
9246  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9247  * of those edges.
9248  *
9249  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9250  */
9251 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9252 {
9253   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9254   if(!cm.isQuadratic())
9255     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9256   else
9257     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9258 }
9259
9260 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9261 {
9262   bool isQuad(false);
9263   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9264     {
9265       const INTERP_KERNEL::Edge *ee(*it);
9266       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9267         isQuad=true;
9268     }
9269   if(!isQuad)
9270     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9271   else
9272     {
9273       const double *coo(mesh2D->getCoords()->begin());
9274       std::size_t sz(conn.size());
9275       std::vector<double> addCoo;
9276       std::vector<int> conn2(conn);
9277       int offset(mesh2D->getNumberOfNodes());
9278       for(std::size_t i=0;i<sz;i++)
9279         {
9280           double tmp[2];
9281           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9282           addCoo.insert(addCoo.end(),tmp,tmp+2);
9283           conn2.push_back(offset+(int)i);
9284         }
9285       mesh2D->getCoords()->rearrange(1);
9286       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9287       mesh2D->getCoords()->rearrange(2);
9288       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9289     }
9290 }
9291
9292 /*!
9293  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9294  *
9295  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9296  * a set of edges defined in \a splitMesh1D.
9297  */
9298 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9299                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9300 {
9301   std::size_t nb(edge1Bis.size()/2);
9302   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9303   int iEnd(splitMesh1D->getNumberOfCells());
9304   if(iEnd==0)
9305     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9306   std::size_t ii,jj;
9307   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9308   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9309   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9310   //
9311   if(jj==nb)
9312     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9313       out0.resize(1); out1.resize(1);
9314       std::vector<int>& connOut(out0[0]);
9315       connOut.resize(nbOfEdgesOf2DCellSplit);
9316       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9317       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9318       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9319         {
9320           connOut[kk]=edge1Bis[2*kk];
9321           edgesPtr[kk]=edge1BisPtr[2*kk];
9322         }
9323     }
9324   else
9325     {
9326       // [i,iEnd[ contains the
9327       out0.resize(2); out1.resize(2);
9328       std::vector<int>& connOutLeft(out0[0]);
9329       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9330       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9331       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9332       for(std::size_t k=ii;k<jj+1;k++)
9333         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9334       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9335       for(int ik=0;ik<iEnd;ik++)
9336         {
9337           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9338           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9339           ees[ik]=ee;
9340         }
9341       for(int ik=iEnd-1;ik>=0;ik--)
9342         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9343       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9344         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9345       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9346       for(int ik=0;ik<iEnd;ik++)
9347         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9348       eright.insert(eright.end(),ees.begin(),ees.end());
9349     }
9350 }
9351
9352 /// @endcond
9353
9354 /// @cond INTERNAL
9355
9356 struct CellInfo
9357 {
9358 public:
9359   CellInfo() { }
9360   CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9361 public:
9362   std::vector<int> _edges;
9363   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9364 };
9365
9366 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9367 {
9368   std::size_t nbe(edges.size());
9369   std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9370   for(std::size_t i=0;i<nbe;i++)
9371     {
9372       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9373       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9374     }
9375   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9376   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9377   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9378 }
9379
9380 class EdgeInfo
9381 {
9382 public:
9383   EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9384   EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9385   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9386   void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9387   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9388 private:
9389   int _istart;
9390   int _iend;
9391   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9392   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9393   int _left;
9394   int _right;
9395 };
9396
9397 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9398 {
9399   const MEDCouplingUMesh *mesh(_mesh);
9400   if(mesh)
9401     return ;
9402   if(_right<pos)
9403     return ;
9404   if(_left>pos)
9405     { _left++; _right++; return ; }
9406   if(_right==pos)
9407     {
9408       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9409       if((isLeft && isRight) || (!isLeft && !isRight))
9410         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9411       if(isLeft)
9412         return ;
9413       if(isRight)
9414         {
9415           _right++;
9416           return ;
9417         }
9418     }
9419   if(_left==pos)
9420     {
9421       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9422       if((isLeft && isRight) || (!isLeft && !isRight))
9423         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9424       if(isLeft)
9425         {
9426           _right++;
9427           return ;
9428         }
9429       if(isRight)
9430         {
9431           _left++;
9432           _right++;
9433           return ;
9434         }
9435     }
9436 }
9437
9438 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9439 {
9440   const MEDCouplingUMesh *mesh(_mesh);
9441   if(!mesh)
9442     {
9443       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9444     }
9445   else
9446     {// not fully splitting cell case
9447       if(mesh2D->getNumberOfCells()==1)
9448         {//little optimization. 1 cell no need to find in which cell mesh is !
9449           neighbors[0]=offset; neighbors[1]=offset;
9450           return;
9451         }
9452       else
9453         {
9454           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9455           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9456           if(cellId==-1)
9457             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9458           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9459         }
9460     }
9461 }
9462
9463 class VectorOfCellInfo
9464 {
9465 public:
9466   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9467   std::size_t size() const { return _pool.size(); }
9468   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9469   void setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs);
9470   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9471   const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9472   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9473   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9474 private:
9475   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9476   void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9477   const CellInfo& get(int pos) const;
9478   CellInfo& get(int pos);
9479 private:
9480   std::vector<CellInfo> _pool;
9481   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9482   std::vector<EdgeInfo> _edge_info;
9483 };
9484
9485 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9486 {
9487   _pool[0]._edges=edges;
9488   _pool[0]._edges_ptr=edgesPtr;
9489 }
9490
9491 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9492 {
9493   if(_pool.empty())
9494     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9495   if(_pool.size()==1)
9496     return 0;
9497   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9498   if(!zeMesh)
9499     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9500   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9501   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9502 }
9503
9504 void VectorOfCellInfo::setMeshAt(int pos, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh, int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh1DInCase, const std::vector< std::vector<int> >& edges, const std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& edgePtrs)
9505 {
9506   get(pos);//to check pos
9507   bool isFast(pos==0 && _pool.size()==1);
9508   std::size_t sz(edges.size());
9509   // dealing with edges
9510   if(sz==1)
9511     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9512   else
9513     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9514   //
9515   std::vector<CellInfo> pool(_pool.size()-1+sz);
9516   for(int i=0;i<pos;i++)
9517     pool[i]=_pool[i];
9518   for(std::size_t j=0;j<sz;j++)
9519     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9520   for(int i=pos+1;i<(int)_pool.size();i++)
9521     pool[i+sz-1]=_pool[i];
9522   _pool=pool;
9523   //
9524   if(sz==2)
9525     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9526   //
9527   if(isFast)
9528     {
9529       _ze_mesh=mesh;
9530       return ;
9531     }
9532   //
9533   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9534   if(pos>0)
9535     {
9536       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9537       ms.push_back(elt);
9538     }
9539   ms.push_back(mesh);
9540   if(pos<_ze_mesh->getNumberOfCells()-1)
9541   {
9542     MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9543     ms.push_back(elt);
9544   }
9545   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9546   for(std::size_t j=0;j<ms2.size();j++)
9547     ms2[j]=ms[j];
9548   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9549 }
9550
9551 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9552 {
9553   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9554 }
9555
9556 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9557 {
9558   if(pos<0)
9559     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9560   int ret(0);
9561   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9562     {
9563       if((*it).isInMyRange(pos))
9564         return ret;
9565     }
9566   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9567 }
9568
9569 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9570 {
9571   get(pos);//to check;
9572   if(_edge_info.empty())
9573     return ;
9574   std::size_t sz(_edge_info.size()-1);
9575   for(std::size_t i=0;i<sz;i++)
9576     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9577 }
9578
9579 const CellInfo& VectorOfCellInfo::get(int pos) const
9580 {
9581   if(pos<0 || pos>=(int)_pool.size())
9582     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9583   return _pool[pos];
9584 }
9585
9586 CellInfo& VectorOfCellInfo::get(int pos)
9587 {
9588   if(pos<0 || pos>=(int)_pool.size())
9589     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9590   return _pool[pos];
9591 }
9592
9593 /*!
9594  * Given :
9595  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9596  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9597  *
9598  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9599  *
9600  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9601  *
9602  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9603  */
9604 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9605                                          MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9606 {
9607   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9608   if(nbCellsInSplitMesh1D==0)
9609     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9610   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9611   std::size_t nb(allEdges.size()),jj;
9612   if(nb%2!=0)
9613     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9614   std::vector<int> edge1Bis(nb*2);
9615   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9616   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9617   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9618   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9619   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9620   //
9621   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9622   int *idsLeftRightPtr(idsLeftRight->getPointer());
9623   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9624   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9625     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9626       int iEnd(iStart);
9627       for(;iEnd<nbCellsInSplitMesh1D;)
9628         {
9629           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9630           if(jj!=nb)
9631             break;
9632           else
9633             iEnd++;
9634         }
9635       if(iEnd<nbCellsInSplitMesh1D)
9636         iEnd++;
9637       //
9638       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9639       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9640       //
9641       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9642       retTmp->setCoords(splitMesh1D->getCoords());
9643       retTmp->allocateCells();
9644
9645       std::vector< std::vector<int> > out0;
9646       std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9647
9648       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9649       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9650         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9651       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9652       //
9653       iStart=iEnd;
9654     }
9655   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9656     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9657   return pool.getZeMesh().retn();
9658 }
9659
9660 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9661                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9662                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9663 {
9664   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9665   //
9666   std::vector<int> allEdges;
9667   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9668   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9669     {
9670       int edgeId(std::abs(*it)-1);
9671       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9672       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9673       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9674       if(*it>0)
9675         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9676       else
9677         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9678       std::size_t sz(edge1.size());
9679       for(std::size_t cnt=0;cnt<sz;cnt++)
9680         allEdgesPtr.push_back(ee);
9681     }
9682   //
9683   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9684 }
9685
9686 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9687 {
9688   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9689     {//easy case comparison not
9690       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9691     }
9692   else if(typ1.isQuadratic() && typ2.isQuadratic())
9693     {
9694       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9695       if(!status0)
9696         return false;
9697       if(conn1[2]==conn2[2])
9698         return true;
9699       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9700       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9701       return dist<eps;
9702     }
9703   else
9704     {//only one is quadratic
9705       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9706       if(!status0)
9707         return false;
9708       const double *a(0),*bb(0),*be(0);
9709       if(typ1.isQuadratic())
9710         {
9711           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9712         }
9713       else
9714         {
9715           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9716         }
9717       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9718       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9719       return dist<eps;
9720     }
9721 }
9722
9723 /*!
9724  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9725  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9726  *
9727  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9728  */
9729 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9730 {
9731   if(candidatesIn2DEnd==candidatesIn2DBg)
9732     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9733   const double *coo(mesh2DSplit->getCoords()->begin());
9734   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9735     return *candidatesIn2DBg;
9736   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9737   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9738   if(cellIdInMesh1DSplitRelative<0)
9739     cur1D->changeOrientationOfCells();
9740   const int *c1D(cur1D->getNodalConnectivity()->begin());
9741   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9742   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9743     {
9744       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9745       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9746       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9747       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9748       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9749       for(unsigned it2=0;it2<sz;it2++)
9750         {
9751           INTERP_KERNEL::NormalizedCellType typeOfSon;
9752           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9753           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9754           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9755             return *it;
9756         }
9757     }
9758   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9759 }
9760
9761 /// @endcond
9762
9763 /*!
9764  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9765  * Thus the final result contains the aggregation of nodes of \a mesh2D, then nodes of \a mesh1D, then new nodes that are the result of the intersection
9766  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9767  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9768  *
9769  * \param [in] mesh2D - the 2D mesh (spacedim=meshdim=2) to be intersected using \a mesh1D tool. The mesh must be so that each point in the space covered by \a mesh2D
9770  *                      must be covered exactly by one entity, \b no \b more. If it is not the case, some tools are available to heal the mesh (conformize2D, mergeNodes)
9771  * \param [in] mesh1D - the 1D mesh (spacedim=2 meshdim=1) the is the tool that will be used to intersect \a mesh2D. \a mesh1D must be ordered consecutively. If it is not the case
9772  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9773  * \param [in] eps - precision used to perform intersections and localization operations.
9774  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9775  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9776  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9777  *                               So this array has a number of tuples equal to the number of cells of \a splitMesh2D and a number of component equal to 1.
9778  * \param [out] cellIdInMesh1D - the array of pair that gives for each cell id \a i in \a splitMesh1D the cell in \a splitMesh2D on the left for the 1st component
9779  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9780  *                               So this array has a number of tuples equal to the number of cells of \a splitMesh1D and a number of components equal to 2.
9781  *
9782  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9783  */
9784 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9785 {
9786   if(!mesh2D || !mesh1D)
9787     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9788   mesh2D->checkFullyDefined();
9789   mesh1D->checkFullyDefined();
9790   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9791   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9792     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9793   // Step 1: compute all edge intersections (new nodes)
9794   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9795   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9796   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9797   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9798   //
9799   // Build desc connectivity
9800   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9801   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9802   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9803   std::map<int,int> mergedNodes;
9804   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9805   // use mergeNodes to fix intersectEdge1
9806   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9807     {
9808       std::size_t n((*it0).size()/2);
9809       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9810       std::map<int,int>::const_iterator it1;
9811       it1=mergedNodes.find(eltStart);
9812       if(it1!=mergedNodes.end())
9813         (*it0)[0]=(*it1).second;
9814       it1=mergedNodes.find(eltEnd);
9815       if(it1!=mergedNodes.end())
9816         (*it0)[2*n-1]=(*it1).second;
9817     }
9818   //
9819   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9820   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9821   // Step 2: re-order newly created nodes according to the ordering found in m2
9822   std::vector< std::vector<int> > intersectEdge2;
9823   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9824   subDiv2.clear();
9825   // Step 3: compute splitMesh1D
9826   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9827   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9828   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9829       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9831   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9832   // deal with cells in mesh2D that are not cut but only some of their edges are
9833   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9834   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9835   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9836   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s;//ids in mesh2D that are impacted by the fact that some edges of \a mesh1D are part of the edges of those cells
9837   if(!idsInDesc2DToBeRefined->empty())
9838     {
9839       DataArrayInt *out0(0),*outi0(0);
9840       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9841       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9842       out0s=out0;
9843       out0s=out0s->buildUnique();
9844       out0s->sort(true);
9845     }
9846   //
9847   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9848   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9849   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9850   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9851   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9852   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9853   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9854     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9855   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9856   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9857   if((DataArrayInt *)out0s)
9858     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9859   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9860   // OK all is ready to insert in ret2 mesh
9861   if(!untouchedCells->empty())
9862     {// the most easy part, cells in mesh2D not impacted at all
9863       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9864       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9865       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9866     }
9867   if((DataArrayInt *)out0s)
9868     {// here dealing with cells in out0s but not in cellsToBeModified
9869       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9870       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9871       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9872         {
9873           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9874           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9875         }
9876       int offset(ret2->getNumberOfTuples());
9877       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9878       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9879       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9880       int kk(0),*ret3ptr(partOfRet3->getPointer());
9881       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9882         {
9883           int faceId(std::abs(*it)-1);
9884           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9885             {
9886               int tmp(fewModifiedCells->locateValue(*it2));
9887               if(tmp!=-1)
9888                 {
9889                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9890                     ret3ptr[2*kk]=tmp+offset;
9891                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9892                     ret3ptr[2*kk+1]=tmp+offset;
9893                 }
9894               else
9895                 {//the current edge is shared by a 2D cell that will be split just after
9896                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9897                     ret3ptr[2*kk]=-(*it2+1);
9898                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9899                     ret3ptr[2*kk+1]=-(*it2+1);
9900                 }
9901             }
9902         }
9903       m1Desc->setCoords(ret1->getCoords());
9904       ret1NonCol->setCoords(ret1->getCoords());
9905       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9906       if(!outMesh2DSplit.empty())
9907         {
9908           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9909           for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9910             (*itt)->setCoords(da);
9911         }
9912     }
9913   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9914   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9915     {
9916       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9917       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9918       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9919       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9920       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9921       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> splitOfOneCell(BuildMesh2DCutFrom(eps,*it,m1Desc,partOfMesh1CuttingCur2DCell,dd1->begin()+dd2->getIJ(*it,0),dd1->begin()+dd2->getIJ((*it)+1,0),intersectEdge1,ret2->getNumberOfTuples(),partOfRet3));
9922       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9923       outMesh2DSplit.push_back(splitOfOneCell);
9924       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9925         ret2->pushBackSilent(*it);
9926     }
9927   //
9928   std::size_t nbOfMeshes(outMesh2DSplit.size());
9929   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9930   for(std::size_t i=0;i<nbOfMeshes;i++)
9931     tmp[i]=outMesh2DSplit[i];
9932   //
9933   ret1->getCoords()->setInfoOnComponents(compNames);
9934   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9935   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9936   ret3->rearrange(1);
9937   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9938   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9939     {
9940       int old2DCellId(-ret3->getIJ(*it,0)-1);
9941       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9942       ret3->setIJ(*it,0,FindRightCandidateAmong(ret2D,candidates->begin(),candidates->end(),ret1,*it%2==0?-((*it)/2+1):(*it)/2+1,eps));// div by 2 because 2 components natively in ret3
9943     }
9944   ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9945   ret3->rearrange(2);
9946   //
9947   splitMesh1D=ret1.retn();
9948   splitMesh2D=ret2D.retn();
9949   cellIdInMesh2D=ret2.retn();
9950   cellIdInMesh1D=ret3.retn();
9951 }
9952
9953 /**
9954  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9955  * (newly created) nodes corresponding to the edge intersections.
9956  * Output params:
9957  * @param[out] cr, crI connectivity of the resulting mesh
9958  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9959  * TODO: describe input parameters
9960  */
9961 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9962                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9963                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9964                                                          const std::vector<double>& addCoords,
9965                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9966 {
9967   static const int SPACEDIM=2;
9968   const double *coo1(m1->getCoords()->getConstPointer());
9969   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9970   int offset1(m1->getNumberOfNodes());
9971   const double *coo2(m2->getCoords()->getConstPointer());
9972   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9973   int offset2(offset1+m2->getNumberOfNodes());
9974   int offset3(offset2+((int)addCoords.size())/2);
9975   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9976   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9977   // Here a BBTree on 2D-cells, not on segments:
9978   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9979   int ncell1(m1->getNumberOfCells());
9980   crI.push_back(0);
9981   for(int i=0;i<ncell1;i++)
9982     {
9983       std::vector<int> candidates2;
9984       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9985       std::map<INTERP_KERNEL::Node *,int> mapp;
9986       std::map<int,INTERP_KERNEL::Node *> mappRev;
9987       INTERP_KERNEL::QuadraticPolygon pol1;
9988       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9989       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9990       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9991       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9992       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9993       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9994           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9995       //
9996       std::set<INTERP_KERNEL::Edge *> edges1;// store all edges of pol1 that are NOT consumed by intersect cells. If any after iteration over candidates2 -> a part of pol1 should appear in result
9997       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9998       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9999       for(it1.first();!it1.finished();it1.next())
10000         edges1.insert(it1.current()->getPtr());
10001       //
10002       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
10003       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
10004       int ii=0;
10005       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10006         {
10007           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
10008           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
10009           // Complete mapping with elements coming from the current cell it2 in mesh2:
10010           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
10011           // pol2 is the new QP in the final merged result.
10012           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
10013               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
10014         }
10015       ii=0;
10016       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
10017         {
10018           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
10019           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
10020           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
10021           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10022         }
10023       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
10024       // by m2 but that we still want to keep in the final result.
10025       if(!edges1.empty())
10026         {
10027           try
10028           {
10029               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
10030           }
10031           catch(INTERP_KERNEL::Exception& e)
10032           {
10033               std::ostringstream oss; oss << "Error when computing residual of cell #" << i << " in source/m1 mesh ! Maybe the neighbours of this cell in mesh are not well connected !\n" << "The deep reason is the following : " << e.what();
10034               throw INTERP_KERNEL::Exception(oss.str().c_str());
10035           }
10036         }
10037       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10038         (*it).second->decrRef();
10039     }
10040 }
10041
10042 /**
10043  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10044  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10045  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10046  * The caller is to deal with the resulting DataArrayInt.
10047  *  \throw If the coordinate array is not set.
10048  *  \throw If the nodal connectivity of the cells is not defined.
10049  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10050  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10051  *
10052  * \sa DataArrayInt::sortEachPairToMakeALinkedList
10053  */
10054 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10055 {
10056   checkFullyDefined();
10057   if(getMeshDimension()!=1)
10058     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10059
10060   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10061   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10062   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10063   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10064   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10065   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10066   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10067   const int * dsi(_dsi->getConstPointer());
10068   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
10069   m_points=0;
10070   if (dsii->getNumberOfTuples())
10071     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10072
10073   int nc(getNumberOfCells());
10074   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10075   result->alloc(nc,1);
10076
10077   // set of edges not used so far
10078   std::set<int> edgeSet;
10079   for (int i=0; i<nc; edgeSet.insert(i), i++);
10080
10081   int startSeg=0;
10082   int newIdx=0;
10083   // while we have points with only one neighbor segments
10084   do
10085     {
10086       std::list<int> linePiece;
10087       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10088       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10089         {
10090           // Fill the list forward (resp. backward) from the start segment:
10091           int activeSeg = startSeg;
10092           int prevPointId = -20;
10093           int ptId;
10094           while (!edgeSet.empty())
10095             {
10096               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10097                 {
10098                   if (direction==0)
10099                     linePiece.push_back(activeSeg);
10100                   else
10101                     linePiece.push_front(activeSeg);
10102                   edgeSet.erase(activeSeg);
10103                 }
10104
10105               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10106               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10107               if (dsi[ptId] == 1) // hitting the end of the line
10108                 break;
10109               prevPointId = ptId;
10110               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10111               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10112             }
10113         }
10114       // Done, save final piece into DA:
10115       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10116       newIdx += linePiece.size();
10117
10118       // identify next valid start segment (one which is not consumed)
10119       if(!edgeSet.empty())
10120         startSeg = *(edgeSet.begin());
10121     }
10122   while (!edgeSet.empty());
10123   return result.retn();
10124 }
10125
10126 /// @cond INTERNAL
10127
10128 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10129 {
10130   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10131   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10132   if(it==m.end())
10133     throw INTERP_KERNEL::Exception("Internal error in remapping !");
10134   int v((*it).second);
10135   if(v==forbVal0 || v==forbVal1)
10136     return ;
10137   if(std::find(isect.begin(),isect.end(),v)==isect.end())
10138     isect.push_back(v);
10139 }
10140
10141 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10142 {
10143   int sz(c.size());
10144   if(sz<=1)
10145     return false;
10146   bool presenceOfOn(false);
10147   for(int i=0;i<sz;i++)
10148     {
10149       INTERP_KERNEL::ElementaryEdge *e(c[i]);
10150       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10151         continue ;
10152       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10153       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10154     }
10155   return presenceOfOn;
10156 }
10157
10158 /// @endcond
10159
10160 /**
10161  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg
10162  * and in \a subNodesInSegI using \ref numbering-indirect storage mode.
10163  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if
10164  * a minimal creation of new nodes is wanted.
10165  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add
10166  * nodes if a SEG3 is split without information of middle.
10167  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to
10168  * avoid to have a non conform mesh.
10169  *
10170  * \return int - the number of new nodes created (in most of cases 0).
10171  * 
10172  * \throw If \a this is not coherent.
10173  * \throw If \a this has not spaceDim equal to 2.
10174  * \throw If \a this has not meshDim equal to 2.
10175  * \throw If some subcells needed to be split are orphan.
10176  * \sa MEDCouplingUMesh::conformize2D
10177  */
10178 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10179 {
10180   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10181     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10182   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10183   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10184     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10185   if(midOpt==0 && midOptI==0)
10186     {
10187       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10188       return 0;
10189     }
10190   else if(midOpt!=0 && midOptI!=0)
10191     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10192   else
10193     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10194 }
10195
10196 /*!
10197  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10198  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10199  * This method performs a conformization of \b this. So if a edge in \a this can be split into entire edges in \a this this method
10200  * will suppress such edges to use sub edges in \a this. So this method does not add nodes in \a this if merged edges are both linear (INTERP_KERNEL::NORM_SEG2).
10201  * In the other cases new nodes can be created. If any are created, they will be appended at the end of the coordinates object before the invokation of this method.
10202  * 
10203  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10204  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10205  *
10206  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10207  * This method expects that all nodes in \a this are not closer than \a eps.
10208  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10209  * 
10210  * \param [in] eps the relative error to detect merged edges.
10211  * \return DataArrayInt  * - The list of cellIds in \a this that have been subdivided. If empty, nothing changed in \a this (as if it were a const method). The array is a newly allocated array
10212  *                           that the user is expected to deal with.
10213  *
10214  * \throw If \a this is not coherent.
10215  * \throw If \a this has not spaceDim equal to 2.
10216  * \throw If \a this has not meshDim equal to 2.
10217  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10218  */
10219 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10220 {
10221   static const int SPACEDIM=2;
10222   checkCoherency();
10223   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10224     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10225   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10226   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10227   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10228   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10229   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10230   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10231   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10232   std::vector<double> addCoo;
10233   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10234   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10235   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10236   for(int i=0;i<nDescCell;i++)
10237     {
10238       std::vector<int> candidates;
10239       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10240       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10241         if(*it>i)
10242           {
10243             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10244             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10245                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10246             INTERP_KERNEL::MergePoints merge;
10247             INTERP_KERNEL::QuadraticPolygon c1,c2;
10248             e1->intersectWith(e2,merge,c1,c2);
10249             e1->decrRef(); e2->decrRef();
10250             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10251               overlapEdge[i].push_back(*it);
10252             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10253               overlapEdge[*it].push_back(i);
10254           }
10255     }
10256   // splitting done. sort intersect point in intersectEdge.
10257   std::vector< std::vector<int> > middle(nDescCell);
10258   int nbOf2DCellsToBeSplit(0);
10259   bool middleNeedsToBeUsed(false);
10260   std::vector<bool> cells2DToTreat(nDescCell,false);
10261   for(int i=0;i<nDescCell;i++)
10262     {
10263       std::vector<int>& isect(intersectEdge[i]);
10264       int sz((int)isect.size());
10265       if(sz>1)
10266         {
10267           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10268           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10269           e->sortSubNodesAbs(coords,isect);
10270           e->decrRef();
10271         }
10272       if(sz!=0)
10273         {
10274           int idx0(rdi[i]),idx1(rdi[i+1]);
10275           if(idx1-idx0!=1)
10276             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10277           if(!cells2DToTreat[rd[idx0]])
10278             {
10279               cells2DToTreat[rd[idx0]]=true;
10280               nbOf2DCellsToBeSplit++;
10281             }
10282           // try to reuse at most eventual 'middle' of SEG3
10283           std::vector<int>& mid(middle[i]);
10284           mid.resize(sz+1,-1);
10285           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10286             {
10287               middleNeedsToBeUsed=true;
10288               const std::vector<int>& candidates(overlapEdge[i]);
10289               std::vector<int> trueCandidates;
10290               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10291                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10292                   trueCandidates.push_back(*itc);
10293               int stNode(c[ci[i]+1]),endNode(isect[0]);
10294               for(int j=0;j<sz+1;j++)
10295                 {
10296                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10297                     {
10298                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10299                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10300                         { mid[j]=*itc; break; }
10301                     }
10302                   stNode=endNode;
10303                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10304                 }
10305             }
10306         }
10307     }
10308   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10309   if(nbOf2DCellsToBeSplit==0)
10310     return ret.retn();
10311   //
10312   int *retPtr(ret->getPointer());
10313   for(int i=0;i<nCell;i++)
10314     if(cells2DToTreat[i])
10315       *retPtr++=i;
10316   //
10317   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10318   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10319   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10320   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10321   if(middleNeedsToBeUsed)
10322     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10323   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10324   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10325   setCoords(modif->getCoords());//if nbOfNodesCreated==0 modif and this have the same coordinates pointer so this line has no effect. But for quadratic cases this line is important.
10326   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10327   {
10328     bool areNodesMerged; int newNbOfNodes;
10329     if(nbOfNodesCreated!=0)
10330       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10331   }
10332   return ret.retn();
10333 }
10334
10335 /*!
10336  * This non const method works on 2D mesh. This method scans every cell in \a this and look if each edge constituting this cell is not mergeable with neighbors edges of that cell.
10337  * If yes, the cell is "repaired" to minimize at most its number of edges. So this method do not change the overall shape of cells in \a this (with eps precision).
10338  * This method do not take care of shared edges between cells, so this method can lead to a non conform mesh (\a this). If a conform mesh is required you're expected
10339  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10340  * This method works on any 2D geometric types of cell (even static one). If a cell is touched its type becomes dynamic automaticaly. For 2D "repaired" quadratic cells
10341  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10342  *
10343  * If the returned array is empty it means that nothing has changed in \a this (as if it were a const method). If the array is not empty the connectivity of \a this is modified
10344  * using new instance, idem for coordinates.
10345  *
10346  * If \a this is constituted by only linear 2D cells, this method is close to the computation of the convex hull of each cells in \a this.
10347  * 
10348  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10349  *
10350  * \throw If \a this is not coherent.
10351  * \throw If \a this has not spaceDim equal to 2.
10352  * \throw If \a this has not meshDim equal to 2.
10353  * 
10354  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10355  */
10356 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10357 {
10358   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10359   checkCoherency();
10360   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10361     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10362   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10363   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10364   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10365   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10366   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10367   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10368   const double *coords(_coords->begin());
10369   int *newciptr(newci->getPointer());
10370   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10371     {
10372       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10373         ret->pushBackSilent(i);
10374       newciptr[1]=newc->getNumberOfTuples();
10375     }
10376   //
10377   if(ret->empty())
10378     return ret.retn();
10379   if(!appendedCoords->empty())
10380     {
10381       appendedCoords->rearrange(2);
10382       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10383       //non const part
10384       setCoords(newCoords);
10385     }
10386   //non const part
10387   setConnectivity(newc,newci,true);
10388   return ret.retn();
10389 }
10390
10391 /*!
10392  * \param [out] intersectEdge1 - for each cell in \a m1Desc returns the result of the split. The result is given using pair of int given resp start and stop.
10393  *                               So for all edge \a i in \a m1Desc \a  intersectEdge1[i] is of length 2*n where n is the number of sub edges.
10394  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10395  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10396  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10397  * \param [out] addCoo - nodes to be append at the end
10398  * \param [out] mergedNodes - gives all pair of nodes of \a m2Desc that have same location than some nodes in \a m1Desc. key is id in \a m2Desc offseted and value is id in \a m1Desc.
10399  */
10400 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10401                                          std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2, std::vector<double>& addCoo, std::map<int,int>& mergedNodes)
10402 {
10403   static const int SPACEDIM=2;
10404   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10405   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10406   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10407   // Build BB tree of all edges in the tool mesh (second mesh)
10408   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10409   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10410   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10411   intersectEdge1.resize(nDescCell1);
10412   colinear2.resize(nDescCell2);
10413   subDiv2.resize(nDescCell2);
10414   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10415
10416   std::vector<int> candidates1(1);
10417   int offset1(m1Desc->getNumberOfNodes());
10418   int offset2(offset1+m2Desc->getNumberOfNodes());
10419   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10420     {
10421       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10422       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10423       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10424         {
10425           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10426           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10427           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10428           candidates1[0]=i;
10429           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10430           // This following part is to avoid that some removed nodes (for example due to a merge between pol1 and pol2) are replaced by a newly created one
10431           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10432           std::set<INTERP_KERNEL::Node *> nodes;
10433           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10434           std::size_t szz(nodes.size());
10435           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10436           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10437           for(std::size_t iii=0;iii<szz;iii++,itt++)
10438             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10439           // end of protection
10440           // Performs egde cutting:
10441           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10442           delete pol2;
10443           delete pol1;
10444         }
10445       else
10446         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10447         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10448     }
10449 }
10450
10451 /*!
10452  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10453  * It builds the descending connectivity of the two meshes, and then using a binary tree
10454  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10455  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10456  */
10457 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10458                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10459                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10460                                                    std::vector<double>& addCoo,
10461                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10462 {
10463   // Build desc connectivity
10464   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10465   desc2=DataArrayInt::New();
10466   descIndx2=DataArrayInt::New();
10467   revDesc2=DataArrayInt::New();
10468   revDescIndx2=DataArrayInt::New();
10469   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10471   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10472   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10473   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10474   std::map<int,int> notUsedMap;
10475   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10476   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10477   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10478 }
10479
10480 /*!
10481  * This method performs the 2nd step of Partition of 2D mesh.
10482  * This method has 4 inputs :
10483  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10484  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10485  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10486  * The aim of this method is to sort the splitting nodes, if any, and to put them in 'intersectEdge' output parameter based on edges of mesh 'm2'
10487  * Nodes end up lying consecutively on a cutted edge.
10488  * \param m1 is expected to be a mesh of meshDimension equal to 1 and spaceDim equal to 2. No check of that is performed by this method.
10489  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10490  * \param m2 is expected to be a mesh of meshDimension equal to 1 and spaceDim equal to 2. No check of that is performed by this method.
10491  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10492  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10493  */
10494 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10495                                            const std::vector<double>& addCoo,
10496                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10497 {
10498   int offset1=m1->getNumberOfNodes();
10499   int ncell=m2->getNumberOfCells();
10500   const int *c=m2->getNodalConnectivity()->getConstPointer();
10501   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10502   const double *coo=m2->getCoords()->getConstPointer();
10503   const double *cooBis=m1->getCoords()->getConstPointer();
10504   int offset2=offset1+m2->getNumberOfNodes();
10505   intersectEdge.resize(ncell);
10506   for(int i=0;i<ncell;i++,cI++)
10507     {
10508       const std::vector<int>& divs=subDiv[i];
10509       int nnode=cI[1]-cI[0]-1;
10510       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10511       std::map<INTERP_KERNEL::Node *, int> mapp22;
10512       for(int j=0;j<nnode;j++)
10513         {
10514           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10515           int nnid=c[(*cI)+j+1];
10516           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10517           mapp22[nn]=nnid+offset1;
10518         }
10519       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10520       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10521         ((*it).second.first)->decrRef();
10522       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10523       std::map<INTERP_KERNEL::Node *,int> mapp3;
10524       for(std::size_t j=0;j<divs.size();j++)
10525         {
10526           int id=divs[j];
10527           INTERP_KERNEL::Node *tmp=0;
10528           if(id<offset1)
10529             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10530           else if(id<offset2)
10531             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10532           else
10533             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10534           addNodes[j]=tmp;
10535           mapp3[tmp]=id;
10536         }
10537       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10538       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10539         (*it)->decrRef();
10540       e->decrRef();
10541     }
10542 }
10543
10544 /*!
10545  * This method is part of the Slice3D algorithm. It is the first step of assembly process, ones coordinates have been computed (by MEDCouplingUMesh::split3DCurveWithPlane method).
10546  * This method allows to compute given the status of 3D curve cells and the descending connectivity 3DSurf->3DCurve to deduce the intersection of each 3D surf cells
10547  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10548  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10549  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10550  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10551  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10552  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10553  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10554  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10555  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10556  * \param [out] cut3DSuf input/output param.
10557  */
10558 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10559                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10560                                                    const int *desc, const int *descIndx, 
10561                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10562 {
10563   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10564   int nbOf3DSurfCell=(int)cut3DSurf.size();
10565   for(int i=0;i<nbOf3DSurfCell;i++)
10566     {
10567       std::vector<int> res;
10568       int offset=descIndx[i];
10569       int nbOfSeg=descIndx[i+1]-offset;
10570       for(int j=0;j<nbOfSeg;j++)
10571         {
10572           int edgeId=desc[offset+j];
10573           int status=cut3DCurve[edgeId];
10574           if(status!=-2)
10575             {
10576               if(status>-1)
10577                 res.push_back(status);
10578               else
10579                 {
10580                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10581                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10582                 }
10583             }
10584         }
10585       switch(res.size())
10586       {
10587         case 2:
10588           {
10589             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10590             break;
10591           }
10592         case 1:
10593         case 0:
10594           {
10595             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10596             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10597             if(res.size()==2)
10598               {
10599                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10600               }
10601             else
10602               {
10603                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10604               }
10605             break;
10606           }
10607         default:
10608           {// case when plane is on a multi colinear edge of a polyhedron
10609             if((int)res.size()==2*nbOfSeg)
10610               {
10611                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10612               }
10613             else
10614               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10615           }
10616       }
10617     }
10618 }
10619
10620 /*!
10621  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10622  * This method is part of the Slice3D algorithm. It is the second step of assembly process, ones coordinates have been computed (by MEDCouplingUMesh::split3DCurveWithPlane method).
10623  * This method allows to compute given the result of 3D surf cells with plane and the descending connectivity 3D->3DSurf to deduce the intersection of each 3D cells
10624  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10625  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10626  * \param desc is the descending connectivity 3D->3DSurf
10627  * \param descIndx is the descending connectivity index 3D->3DSurf
10628  */
10629 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10630                                                   const int *desc, const int *descIndx,
10631                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10632 {
10633   checkFullyDefined();
10634   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10635     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10636   const int *nodal3D=_nodal_connec->getConstPointer();
10637   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10638   int nbOfCells=getNumberOfCells();
10639   for(int i=0;i<nbOfCells;i++)
10640     {
10641       std::map<int, std::set<int> > m;
10642       int offset=descIndx[i];
10643       int nbOfFaces=descIndx[i+1]-offset;
10644       int start=-1;
10645       int end=-1;
10646       for(int j=0;j<nbOfFaces;j++)
10647         {
10648           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10649           if(p.first!=-1 && p.second!=-1)
10650             {
10651               if(p.first!=-2)
10652                 {
10653                   start=p.first; end=p.second;
10654                   m[p.first].insert(p.second);
10655                   m[p.second].insert(p.first);
10656                 }
10657               else
10658                 {
10659                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10660                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10661                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10662                   INTERP_KERNEL::NormalizedCellType cmsId;
10663                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10664                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10665                   for(unsigned k=0;k<nbOfNodesSon;k++)
10666                     {
10667                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10668                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10669                     }
10670                 }
10671             }
10672         }
10673       if(m.empty())
10674         continue;
10675       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10676       int prev=end;
10677       while(end!=start)
10678         {
10679           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10680           const std::set<int>& s=(*it).second;
10681           std::set<int> s2; s2.insert(prev);
10682           std::set<int> s3;
10683           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10684           if(s3.size()==1)
10685             {
10686               int val=*s3.begin();
10687               conn.push_back(start);
10688               prev=start;
10689               start=val;
10690             }
10691           else
10692             start=end;
10693         }
10694       conn.push_back(end);
10695       if(conn.size()>3)
10696         {
10697           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10698           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10699           cellIds->pushBackSilent(i);
10700         }
10701     }
10702 }
10703
10704 /*!
10705  * 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
10706  * 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
10707  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10708  * 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
10709  * 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.
10710  * 
10711  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10712  */
10713 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10714 {
10715   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10716   if(sz>=4)
10717     {
10718       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10719       if(cm.getDimension()==2)
10720         {
10721           const int *node=nodalConnBg+1;
10722           int startNode=*node++;
10723           double refX=coords[2*startNode];
10724           for(;node!=nodalConnEnd;node++)
10725             {
10726               if(coords[2*(*node)]<refX)
10727                 {
10728                   startNode=*node;
10729                   refX=coords[2*startNode];
10730                 }
10731             }
10732           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10733           refX=1e300;
10734           double tmp1;
10735           double tmp2[2];
10736           double angle0=-M_PI/2;
10737           //
10738           int nextNode=-1;
10739           int prevNode=-1;
10740           double resRef;
10741           double angleNext=0.;
10742           while(nextNode!=startNode)
10743             {
10744               nextNode=-1;
10745               resRef=1e300;
10746               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10747                 {
10748                   if(*node!=tmpOut.back() && *node!=prevNode)
10749                     {
10750                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10751                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10752                       double res;
10753                       if(angleM<=angle0)
10754                         res=angle0-angleM;
10755                       else
10756                         res=angle0-angleM+2.*M_PI;
10757                       if(res<resRef)
10758                         {
10759                           nextNode=*node;
10760                           resRef=res;
10761                           angleNext=angleM;
10762                         }
10763                     }
10764                 }
10765               if(nextNode!=startNode)
10766                 {
10767                   angle0=angleNext-M_PI;
10768                   if(angle0<-M_PI)
10769                     angle0+=2*M_PI;
10770                   prevNode=tmpOut.back();
10771                   tmpOut.push_back(nextNode);
10772                 }
10773             }
10774           std::vector<int> tmp3(2*(sz-1));
10775           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10776           std::copy(nodalConnBg+1,nodalConnEnd,it);
10777           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10778             {
10779               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10780               return false;
10781             }
10782           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10783             {
10784               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10785               return false;
10786             }
10787           else
10788             {
10789               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10790               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10791               return true;
10792             }
10793         }
10794       else
10795         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10796     }
10797   else
10798     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10799 }
10800
10801 /*!
10802  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10803  * This method will not impact the size of inout parameter \b arrIndx but the size of \b arr will be modified in case of suppression.
10804  * 
10805  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10806  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10807  * \param [in,out] arr array in which the remove operation will be done.
10808  * \param [in,out] arrIndx array in the remove operation will modify
10809  * \param [in] offsetForRemoval (by default 0) offset so that for each i in [0,arrIndx->getNumberOfTuples()-1) removal process will be performed in the following range [arr+arrIndx[i]+offsetForRemoval,arr+arr[i+1])
10810  * \return true if \b arr and \b arrIndx have been modified, false if not.
10811  */
10812 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10813 {
10814   if(!arrIndx || !arr)
10815     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10816   if(offsetForRemoval<0)
10817     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10818   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10819   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10820   int *arrIPtr=arrIndx->getPointer();
10821   *arrIPtr++=0;
10822   int previousArrI=0;
10823   const int *arrPtr=arr->getConstPointer();
10824   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10825   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10826     {
10827       if(*arrIPtr-previousArrI>offsetForRemoval)
10828         {
10829           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10830             {
10831               if(s.find(*work)==s.end())
10832                 arrOut.push_back(*work);
10833             }
10834         }
10835       previousArrI=*arrIPtr;
10836       *arrIPtr=(int)arrOut.size();
10837     }
10838   if(arr->getNumberOfTuples()==(int)arrOut.size())
10839     return false;
10840   arr->alloc((int)arrOut.size(),1);
10841   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10842   return true;
10843 }
10844
10845 /*!
10846  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10847  * (\ref numbering-indirect).
10848  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10849  * The selection of extraction is done standardly in new2old format.
10850  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10851  *
10852  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10853  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10854  * \param [in] arrIn arr origin array from which the extraction will be done.
10855  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10856  * \param [out] arrOut the resulting array
10857  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10858  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10859  */
10860 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10861                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10862 {
10863   if(!arrIn || !arrIndxIn)
10864     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10865   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10866   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10867     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10868   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10869   const int *arrInPtr=arrIn->getConstPointer();
10870   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10871   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10872   if(nbOfGrps<0)
10873     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10874   int maxSizeOfArr=arrIn->getNumberOfTuples();
10875   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10876   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10877   arrIo->alloc((int)(sz+1),1);
10878   const int *idsIt=idsOfSelectBg;
10879   int *work=arrIo->getPointer();
10880   *work++=0;
10881   int lgth=0;
10882   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10883     {
10884       if(*idsIt>=0 && *idsIt<nbOfGrps)
10885         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10886       else
10887         {
10888           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10889           throw INTERP_KERNEL::Exception(oss.str().c_str());
10890         }
10891       if(lgth>=work[-1])
10892         *work=lgth;
10893       else
10894         {
10895           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10896           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10897           throw INTERP_KERNEL::Exception(oss.str().c_str());
10898         }
10899     }
10900   arro->alloc(lgth,1);
10901   work=arro->getPointer();
10902   idsIt=idsOfSelectBg;
10903   for(std::size_t i=0;i<sz;i++,idsIt++)
10904     {
10905       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10906         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10907       else
10908         {
10909           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10910           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10911           throw INTERP_KERNEL::Exception(oss.str().c_str());
10912         }
10913     }
10914   arrOut=arro.retn();
10915   arrIndexOut=arrIo.retn();
10916 }
10917
10918 /*!
10919  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn
10920  * (\ref numbering-indirect).
10921  * This method returns the result of the extraction ( specified by a set of ids with a slice given by \a idsOfSelectStart, \a idsOfSelectStop and \a idsOfSelectStep ).
10922  * The selection of extraction is done standardly in new2old format.
10923  * This method returns indexed arrays (\ref numbering-indirect) using 2 arrays (arrOut,arrIndexOut).
10924  *
10925  * \param [in] idsOfSelectStart begin of set of ids of the input extraction (included)
10926  * \param [in] idsOfSelectStop end of set of ids of the input extraction (excluded)
10927  * \param [in] idsOfSelectStep
10928  * \param [in] arrIn arr origin array from which the extraction will be done.
10929  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10930  * \param [out] arrOut the resulting array
10931  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10932  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10933  */
10934 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10935                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10936 {
10937   if(!arrIn || !arrIndxIn)
10938     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10939   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10940   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10941     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10942   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10943   const int *arrInPtr=arrIn->getConstPointer();
10944   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10945   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10946   if(nbOfGrps<0)
10947     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10948   int maxSizeOfArr=arrIn->getNumberOfTuples();
10949   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10950   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10951   arrIo->alloc((int)(sz+1),1);
10952   int idsIt=idsOfSelectStart;
10953   int *work=arrIo->getPointer();
10954   *work++=0;
10955   int lgth=0;
10956   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10957     {
10958       if(idsIt>=0 && idsIt<nbOfGrps)
10959         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10960       else
10961         {
10962           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10963           throw INTERP_KERNEL::Exception(oss.str().c_str());
10964         }
10965       if(lgth>=work[-1])
10966         *work=lgth;
10967       else
10968         {
10969           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10970           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10971           throw INTERP_KERNEL::Exception(oss.str().c_str());
10972         }
10973     }
10974   arro->alloc(lgth,1);
10975   work=arro->getPointer();
10976   idsIt=idsOfSelectStart;
10977   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10978     {
10979       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10980         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10981       else
10982         {
10983           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10984           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10985           throw INTERP_KERNEL::Exception(oss.str().c_str());
10986         }
10987     }
10988   arrOut=arro.retn();
10989   arrIndexOut=arrIo.retn();
10990 }
10991
10992 /*!
10993  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10994  * This method builds an output pair (\b arrOut,\b arrIndexOut) that is a copy from \b arrIn for all cell ids \b not \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) and for
10995  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10996  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10997  *
10998  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10999  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11000  * \param [in] arrIn arr origin array from which the extraction will be done.
11001  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11002  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
11003  * \param [in] srcArrIndex index array of \b srcArr
11004  * \param [out] arrOut the resulting array
11005  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11006  * 
11007  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11008  */
11009 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11010                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11011                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11012 {
11013   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11014     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
11015   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11016   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11017   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11018   std::vector<bool> v(nbOfTuples,true);
11019   int offset=0;
11020   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11021   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11022   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11023     {
11024       if(*it>=0 && *it<nbOfTuples)
11025         {
11026           v[*it]=false;
11027           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
11028         }
11029       else
11030         {
11031           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11032           throw INTERP_KERNEL::Exception(oss.str().c_str());
11033         }
11034     }
11035   srcArrIndexPtr=srcArrIndex->getConstPointer();
11036   arrIo->alloc(nbOfTuples+1,1);
11037   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11038   const int *arrInPtr=arrIn->getConstPointer();
11039   const int *srcArrPtr=srcArr->getConstPointer();
11040   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11041   int *arroPtr=arro->getPointer();
11042   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11043     {
11044       if(v[ii])
11045         {
11046           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11047           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11048         }
11049       else
11050         {
11051           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11052           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11053           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11054         }
11055     }
11056   arrOut=arro.retn();
11057   arrIndexOut=arrIo.retn();
11058 }
11059
11060 /*!
11061  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11062  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11063  *
11064  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11065  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11066  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11067  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11068  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11069  * \param [in] srcArrIndex index array of \b srcArr
11070  * 
11071  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11072  */
11073 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11074                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11075 {
11076   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11077     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11078   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11079   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11080   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11081   int *arrInOutPtr=arrInOut->getPointer();
11082   const int *srcArrPtr=srcArr->getConstPointer();
11083   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11084     {
11085       if(*it>=0 && *it<nbOfTuples)
11086         {
11087           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11088             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11089           else
11090             {
11091               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " id (idsOfSelectBg[" << std::distance(idsOfSelectBg,it)<< "]) is " << *it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11092               throw INTERP_KERNEL::Exception(oss.str().c_str());
11093             }
11094         }
11095       else
11096         {
11097           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11098           throw INTERP_KERNEL::Exception(oss.str().c_str());
11099         }
11100     }
11101 }
11102
11103 /*!
11104  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11105  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11106  * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 looking at arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
11107  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11108  * A negative value in \b arrIn means that it is ignored.
11109  * 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.
11110  * 
11111  * \param [in] arrIn arr origin array from which the extraction will be done.
11112  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11113  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11114  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11115  */
11116 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11117 {
11118   int seed=0,nbOfDepthPeelingPerformed=0;
11119   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11120 }
11121
11122 /*!
11123  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11124  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11125  * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 regarding arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
11126  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11127  * A negative value in \b arrIn means that it is ignored.
11128  * 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.
11129  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11130  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11131  * \param [in] arrIn arr origin array from which the extraction will be done.
11132  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11133  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11134  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11135  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11136  * \sa MEDCouplingUMesh::partitionBySpreadZone
11137  */
11138 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11139 {
11140   nbOfDepthPeelingPerformed=0;
11141   if(!arrIndxIn)
11142     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11143   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11144   if(nbOfTuples<=0)
11145     {
11146       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11147       return ret;
11148     }
11149   //
11150   std::vector<bool> fetched(nbOfTuples,false);
11151   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11152 }
11153
11154 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11155 {
11156   nbOfDepthPeelingPerformed=0;
11157   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11158     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11159   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11160   std::vector<bool> fetched2(nbOfTuples,false);
11161   int i=0;
11162   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11163     {
11164       if(*seedElt>=0 && *seedElt<nbOfTuples)
11165         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11166       else
11167         { std::ostringstream oss; oss << "MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : At pos #" << i << " of seeds value is " << *seedElt << "! Should be in [0," << nbOfTuples << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
11168     }
11169   const int *arrInPtr=arrIn->getConstPointer();
11170   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11171   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11172   std::vector<int> idsToFetch1(seedBg,seedEnd);
11173   std::vector<int> idsToFetch2;
11174   std::vector<int> *idsToFetch=&idsToFetch1;
11175   std::vector<int> *idsToFetchOther=&idsToFetch2;
11176   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11177     {
11178       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11179         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11180           if(!fetched[*it2])
11181             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11182       std::swap(idsToFetch,idsToFetchOther);
11183       idsToFetchOther->clear();
11184       nbOfDepthPeelingPerformed++;
11185     }
11186   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11187   i=0;
11188   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11189   int *retPtr=ret->getPointer();
11190   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11191     if(*it)
11192       *retPtr++=i;
11193   return ret.retn();
11194 }
11195
11196 /*!
11197  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11198  * This method builds an output pair (\b arrOut,\b arrIndexOut) that is a copy from \b arrIn for all cell ids \b not \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) and for
11199  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11200  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11201  *
11202  * \param [in] start begin of set of ids of the input extraction (included)
11203  * \param [in] end end of set of ids of the input extraction (excluded)
11204  * \param [in] step step of the set of ids in range mode.
11205  * \param [in] arrIn arr origin array from which the extraction will be done.
11206  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11207  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11208  * \param [in] srcArrIndex index array of \b srcArr
11209  * \param [out] arrOut the resulting array
11210  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11211  * 
11212  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11213  */
11214 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11215                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11216                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11217 {
11218   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11219     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11220   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11221   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11222   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11223   int offset=0;
11224   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11225   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11226   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11227   int it=start;
11228   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11229     {
11230       if(it>=0 && it<nbOfTuples)
11231         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11232       else
11233         {
11234           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11235           throw INTERP_KERNEL::Exception(oss.str().c_str());
11236         }
11237     }
11238   srcArrIndexPtr=srcArrIndex->getConstPointer();
11239   arrIo->alloc(nbOfTuples+1,1);
11240   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11241   const int *arrInPtr=arrIn->getConstPointer();
11242   const int *srcArrPtr=srcArr->getConstPointer();
11243   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11244   int *arroPtr=arro->getPointer();
11245   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11246     {
11247       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11248       if(pos<0)
11249         {
11250           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11251           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11252         }
11253       else
11254         {
11255           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11256           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11257         }
11258     }
11259   arrOut=arro.retn();
11260   arrIndexOut=arrIo.retn();
11261 }
11262
11263 /*!
11264  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11265  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11266  *
11267  * \param [in] start begin of set of ids of the input extraction (included)
11268  * \param [in] end end of set of ids of the input extraction (excluded)
11269  * \param [in] step step of the set of ids in range mode.
11270  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11271  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11272  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11273  * \param [in] srcArrIndex index array of \b srcArr
11274  * 
11275  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11276  */
11277 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11278                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11279 {
11280   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11281     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11282   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11283   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11284   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11285   int *arrInOutPtr=arrInOut->getPointer();
11286   const int *srcArrPtr=srcArr->getConstPointer();
11287   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11288   int it=start;
11289   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11290     {
11291       if(it>=0 && it<nbOfTuples)
11292         {
11293           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11294             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11295           else
11296             {
11297               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11298               throw INTERP_KERNEL::Exception(oss.str().c_str());
11299             }
11300         }
11301       else
11302         {
11303           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11304           throw INTERP_KERNEL::Exception(oss.str().c_str());
11305         }
11306     }
11307 }
11308
11309 /*!
11310  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11311  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11312  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11313  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11314  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11315  * 
11316  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11317  */
11318 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11319 {
11320   checkFullyDefined();
11321   int mdim=getMeshDimension();
11322   int spaceDim=getSpaceDimension();
11323   if(mdim!=spaceDim)
11324     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11325   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11326   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11327   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11328   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11329   ret->setCoords(getCoords());
11330   ret->allocateCells((int)partition.size());
11331   //
11332   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11333     {
11334       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11335       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11336       switch(mdim)
11337       {
11338         case 2:
11339           cell=tmp->buildUnionOf2DMesh();
11340           break;
11341         case 3:
11342           cell=tmp->buildUnionOf3DMesh();
11343           break;
11344         default:
11345           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11346       }
11347
11348       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11349     }
11350   //
11351   ret->finishInsertingCells();
11352   return ret.retn();
11353 }
11354
11355 /*!
11356  * This method partitions \b this into contiguous zone.
11357  * This method only needs a well defined connectivity. Coordinates are not considered here.
11358  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11359  */
11360 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11361 {
11362   int nbOfCellsCur=getNumberOfCells();
11363   std::vector<DataArrayInt *> ret;
11364   if(nbOfCellsCur<=0)
11365     return ret;
11366   DataArrayInt *neigh=0,*neighI=0;
11367   computeNeighborsOfCells(neigh,neighI);
11368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11369   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11370   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11371   int seed=0;
11372   while(seed<nbOfCellsCur)
11373     {
11374       int nbOfPeelPerformed=0;
11375       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11376       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11377     }
11378   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11379     ret.push_back((*it).retn());
11380   return ret;
11381 }
11382
11383 /*!
11384  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11385  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11386  *
11387  * \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.
11388  * \return a newly allocated DataArrayInt to be managed by the caller.
11389  * \throw In case of \a code has not the right format (typically of size 3*n)
11390  */
11391 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11392 {
11393   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11394   std::size_t nb=code.size()/3;
11395   if(code.size()%3!=0)
11396     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11397   ret->alloc((int)nb,2);
11398   int *retPtr=ret->getPointer();
11399   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11400     {
11401       retPtr[0]=code[3*i+2];
11402       retPtr[1]=code[3*i+2]+code[3*i+1];
11403     }
11404   return ret.retn();
11405 }
11406
11407 /*!
11408  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11409  * All cells in \a this are expected to be linear 3D cells.
11410  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11411  * It leads to an increase to number of cells.
11412  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11413  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11414  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11415  *
11416  * \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.
11417  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11418  * \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. 
11419  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11420  *          an id of old cell producing it. The caller is to delete this array using
11421  *         decrRef() as it is no more needed.
11422  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11423  *
11424  * \warning This method operates on each cells in this independantly ! So it can leads to non conform mesh in returned value ! If you expect to have a conform mesh in output
11425  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11426  * 
11427  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11428  * \throw If \a this is not fully constituted with linear 3D cells.
11429  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11430  */
11431 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11432 {
11433   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11434   checkConnectivityFullyDefined();
11435   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11436     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11437   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11438   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11439   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11440   int *retPt(ret->getPointer());
11441   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11442   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11443   const int *oldc(_nodal_connec->begin());
11444   const int *oldci(_nodal_connec_index->begin());
11445   const double *coords(_coords->begin());
11446   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11447     {
11448       std::vector<int> a; std::vector<double> b;
11449       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11450       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11451       const int *aa(&a[0]);
11452       if(!b.empty())
11453         {
11454           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11455             if(*it<0)
11456               *it=(-(*(it))-1+nbNodes);
11457           addPts->insertAtTheEnd(b.begin(),b.end());
11458           nbNodes+=(int)b.size()/3;
11459         }
11460       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11461         newConn->insertAtTheEnd(aa,aa+4);
11462     }
11463   if(!addPts->empty())
11464     {
11465       addPts->rearrange(3);
11466       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11467       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11468       ret0->setCoords(addPts);
11469     }
11470   else
11471     {
11472       nbOfAdditionalPoints=0;
11473       ret0->setCoords(getCoords());
11474     }
11475   ret0->setNodalConnectivity(newConn);
11476   //
11477   ret->computeOffsets2();
11478   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11479   return ret0.retn();
11480 }
11481
11482 /*!
11483  * It is the linear part of MEDCouplingUMesh::split2DCells. Here no additionnal nodes will be added in \b this. So coordinates pointer remain unchanged (is not even touch). 
11484  *
11485  * \sa MEDCouplingUMesh::split2DCells
11486  */
11487 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11488 {
11489   checkConnectivityFullyDefined();
11490   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11491   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11492   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11493   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11494   int prevPosOfCi(ciPtr[0]);
11495   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11496     {
11497       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11498       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11499       for(int j=0;j<sz;j++)
11500         {
11501           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11502           for(int k=0;k<sz2;k++)
11503             *cPtr++=subPtr[offset2+k];
11504           if(j!=sz-1)
11505             *cPtr++=oldConn[prevPosOfCi+j+2];
11506           deltaSz+=sz2;
11507         }
11508       prevPosOfCi=ciPtr[1];
11509       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11510     }
11511   if(c->end()!=cPtr)
11512     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11513   _nodal_connec->decrRef();
11514   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11515 }
11516
11517 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11518 {
11519   if(id!=-1)
11520     return id;
11521   else
11522     {
11523       int ret(nodesCnter++);
11524       double newPt[2];
11525       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11526       addCoo.insertAtTheEnd(newPt,newPt+2);
11527       return ret;
11528     }
11529 }
11530
11531 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11532 {
11533   if(id!=-1)
11534     return id;
11535   else
11536     {
11537       int ret(nodesCnter++);
11538       double newPt[2];
11539       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11540       addCoo.insertAtTheEnd(newPt,newPt+2);
11541       return ret;
11542     }
11543 }
11544
11545
11546 /// @cond INTERNAL
11547
11548 void EnterTheResultOf2DCellFirst(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
11549 {
11550   int tmp[3];
11551   int trueStart(start>=0?start:nbOfEdges+start);
11552   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11553   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11554   if(linOrArc)
11555     {
11556       if(stp-start>1)
11557         {
11558           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11559           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11560           middles.push_back(tmp3+offset);
11561         }
11562       else
11563         middles.push_back(connBg[trueStart+nbOfEdges]);
11564     }
11565 }
11566
11567 void EnterTheResultOf2DCellMiddle(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
11568 {
11569   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11570   newConnOfCell->pushBackSilent(tmpEnd);
11571   if(linOrArc)
11572     {
11573       if(stp-start>1)
11574         {
11575           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11576           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11577           middles.push_back(tmp3+offset);
11578         }
11579       else
11580         middles.push_back(connBg[start+nbOfEdges]);
11581     }
11582 }
11583
11584 void EnterTheResultOf2DCellEnd(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
11585 {
11586   // only the quadratic point to deal with:
11587   if(linOrArc)
11588     {
11589       if(stp-start>1)
11590         {
11591           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11592           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11593           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11594           middles.push_back(tmp3+offset);
11595         }
11596       else
11597         middles.push_back(connBg[start+nbOfEdges]);
11598     }
11599 }
11600
11601 /// @endcond
11602
11603 /*!
11604  * Returns true if a colinearization has been found in the given cell. If false is returned the content pushed in \a newConnOfCell is equal to [ \a connBg , \a connEnd ) .
11605  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11606  */
11607 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11608 {
11609   std::size_t sz(std::distance(connBg,connEnd));
11610   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11611     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11612   sz--;
11613   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11614   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11615   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11616   unsigned nbOfHit(0); // number of fusions operated
11617   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11618   const unsigned int maxNbOfHit = cm.isQuadratic() ? nbs-2 : nbs-3;  // a quad cell is authorized to end up with only two edges, a linear one has to keep 3 at least
11619   INTERP_KERNEL::NormalizedCellType typeOfSon;
11620   std::vector<int> middles;
11621   bool ret(false);
11622   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11623     {
11624       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11625       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11626       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11627       posEndElt = posBaseElt+1;
11628
11629       // Look backward first: are the final edges of the cells colinear with the first ones?
11630       // This initializes posBaseElt.
11631       if(nbOfTurn==0)
11632         {
11633           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11634             {
11635               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11636               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11637               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11638               bool isColinear=eint->areColinears();
11639               if(isColinear)
11640                 {
11641                   nbOfHit++;
11642                   posBaseElt--;
11643                   ret=true;
11644                 }
11645               delete eint;
11646               eCand->decrRef();
11647               if(!isColinear)
11648                 break;
11649             }
11650         }
11651       // Now move forward:
11652       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11653       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11654         {
11655           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11656           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11657           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11658           bool isColinear(eint->areColinears());
11659           if(isColinear)
11660             {
11661               nbOfHit++;
11662               posEndElt++;
11663               ret=true;
11664             }
11665           delete eint;
11666           eCand->decrRef();
11667           if(!isColinear)
11668               break;
11669         }
11670       //push [posBaseElt,posEndElt) in newConnOfCell using e
11671       // The if clauses below are (volontary) not mutually exclusive: on a quad cell with 2 edges, the end of the connectivity is also its begining!
11672       if(nbOfTurn==0)
11673         // at the begining of the connectivity (insert type)
11674         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11675       else if((nbOfHit+nbOfTurn) != (nbs-1))
11676         // in the middle
11677         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11678       if ((nbOfHit+nbOfTurn) == (nbs-1))
11679         // at the end (only quad points to deal with)
11680         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11681       posBaseElt=posEndElt;
11682       e->decrRef();
11683     }
11684   if(!middles.empty())
11685     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11686   return ret;
11687 }
11688
11689 /*!
11690  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11691  *
11692  * \return  int - the number of new nodes created.
11693  * \sa MEDCouplingUMesh::split2DCells
11694  */
11695 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11696 {
11697   checkCoherency();
11698   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11699   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11700   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11701   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11702   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11703   const double *oldCoordsPtr(getCoords()->begin());
11704   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11705   int prevPosOfCi(ciPtr[0]);
11706   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11707     {
11708       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11709       for(int j=0;j<sz;j++)
11710         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11711       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11712       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11713         {
11714           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11715           if(sz2==0)
11716             {
11717               if(j<sz-1)
11718                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11719               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11720               continue;
11721             }
11722           std::vector<INTERP_KERNEL::Node *> ns(3);
11723           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11724           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11725           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11726           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11727           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11728             {
11729               cPtr[1]=subPtr[offset2+k];
11730               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11731             }
11732           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11733           if(j!=sz-1)
11734             { cPtr[1]=tmpEnd; }
11735           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11736         }
11737       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11738       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11739     }
11740   if(c->end()!=cPtr)
11741     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11742   _nodal_connec->decrRef();
11743   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11744   addCoo->rearrange(2);
11745   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11746   setCoords(coo);
11747   return addCoo->getNumberOfTuples();
11748 }
11749
11750 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11751 {
11752   if(nodalConnec && nodalConnecIndex)
11753     {
11754       types.clear();
11755       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11756       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11757       if(nbOfElem>0)
11758         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11759           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11760     }
11761 }
11762
11763 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11764     _own_cell(true),_cell_id(-1),_nb_cell(0)
11765 {
11766   if(mesh)
11767     {
11768       mesh->incrRef();
11769       _nb_cell=mesh->getNumberOfCells();
11770     }
11771 }
11772
11773 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11774 {
11775   if(_mesh)
11776     _mesh->decrRef();
11777   if(_own_cell)
11778     delete _cell;
11779 }
11780
11781 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11782     _own_cell(false),_cell_id(bg-1),
11783     _nb_cell(end)
11784 {
11785   if(mesh)
11786     mesh->incrRef();
11787 }
11788
11789 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11790 {
11791   _cell_id++;
11792   if(_cell_id<_nb_cell)
11793     {
11794       _cell->next();
11795       return _cell;
11796     }
11797   else
11798     return 0;
11799 }
11800
11801 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11802 {
11803   if(_mesh)
11804     _mesh->incrRef();
11805 }
11806
11807 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11808 {
11809   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11810 }
11811
11812 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11813 {
11814   if(_mesh)
11815     _mesh->decrRef();
11816 }
11817
11818 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11819     _itc(itc),
11820     _bg(bg),_end(end)
11821 {
11822   if(_mesh)
11823     _mesh->incrRef();
11824 }
11825
11826 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11827 {
11828   if(_mesh)
11829     _mesh->decrRef();
11830 }
11831
11832 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11833 {
11834   return _type;
11835 }
11836
11837 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11838 {
11839   return _end-_bg;
11840 }
11841
11842 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11843 {
11844   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11845 }
11846
11847 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11848 {
11849   if(mesh)
11850     {
11851       mesh->incrRef();
11852       _nb_cell=mesh->getNumberOfCells();
11853     }
11854 }
11855
11856 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11857 {
11858   if(_mesh)
11859     _mesh->decrRef();
11860   delete _cell;
11861 }
11862
11863 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11864 {
11865   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11866   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11867   if(_cell_id<_nb_cell)
11868     {
11869       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11870       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11871       int startId=_cell_id;
11872       _cell_id+=nbOfElems;
11873       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11874     }
11875   else
11876     return 0;
11877 }
11878
11879 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11880 {
11881   if(mesh)
11882     {
11883       _conn=mesh->getNodalConnectivity()->getPointer();
11884       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11885     }
11886 }
11887
11888 void MEDCouplingUMeshCell::next()
11889 {
11890   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11891     {
11892       _conn+=_conn_lgth;
11893       _conn_indx++;
11894     }
11895   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11896 }
11897
11898 std::string MEDCouplingUMeshCell::repr() const
11899 {
11900   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11901     {
11902       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11903       oss << " : ";
11904       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11905       return oss.str();
11906     }
11907   else
11908     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11909 }
11910
11911 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11912 {
11913   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11914     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11915   else
11916     return INTERP_KERNEL::NORM_ERROR;
11917 }
11918
11919 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11920 {
11921   lgth=_conn_lgth;
11922   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11923     return _conn;
11924   else
11925     return 0;
11926 }