Salome HOME
Using std::vector<bool> instead of new bool[]
[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 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 };
57
58 MEDCouplingUMesh *MEDCouplingUMesh::New()
59 {
60   return new MEDCouplingUMesh;
61 }
62
63 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
64 {
65   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
66   ret->setName(meshName);
67   ret->setMeshDimension(meshDim);
68   return ret;
69 }
70
71 /*!
72  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
73  * between \a this and the new mesh.
74  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
75  *          delete this mesh using decrRef() as it is no more needed. 
76  */
77 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
78 {
79   return clone(true);
80 }
81
82 /*!
83  * Returns a new MEDCouplingMesh which is a copy of \a this one.
84  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
85  * this mesh are shared by the new mesh.
86  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
87  *          delete this mesh using decrRef() as it is no more needed. 
88  */
89 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
90 {
91   return new MEDCouplingUMesh(*this,recDeepCpy);
92 }
93
94 /*!
95  * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
96  * The coordinates are shared between \a this and the returned instance.
97  * 
98  * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
99  * \sa MEDCouplingUMesh::deepCpy
100  */
101 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
102 {
103   checkConnectivityFullyDefined();
104   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
105   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
106   ret->setConnectivity(c,ci);
107   return ret.retn();
108 }
109
110 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
111 {
112   if(!other)
113     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
114   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
115   if(!otherC)
116     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
117   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
118   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
119 }
120
121 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
122 {
123   std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
124   return ret;
125 }
126
127 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildrenWithNull() const
128 {
129   std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildrenWithNull());
130   ret.push_back(_nodal_connec);
131   ret.push_back(_nodal_connec_index);
132   return ret;
133 }
134
135 void MEDCouplingUMesh::updateTime() const
136 {
137   MEDCouplingPointSet::updateTime();
138   if(_nodal_connec)
139     {
140       updateTimeWith(*_nodal_connec);
141     }
142   if(_nodal_connec_index)
143     {
144       updateTimeWith(*_nodal_connec_index);
145     }
146 }
147
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
149 {
150 }
151
152 /*!
153  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154  * then \a this mesh is most probably is writable, exchangeable and available for most
155  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156  * this method to check that all is in order with \a this mesh.
157  *  \throw If the mesh dimension is not set.
158  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
159  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160  *  \throw If the connectivity data array has more than one component.
161  *  \throw If the connectivity data array has a named component.
162  *  \throw If the connectivity index data array has more than one component.
163  *  \throw If the connectivity index data array has a named component.
164  */
165 void MEDCouplingUMesh::checkCoherency() const
166 {
167   if(_mesh_dim<-1)
168     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
169   if(_mesh_dim!=-1)
170     MEDCouplingPointSet::checkCoherency();
171   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
172     {
173       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
174         {
175           std::ostringstream message;
176           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177           throw INTERP_KERNEL::Exception(message.str().c_str());
178         }
179     }
180   if(_nodal_connec)
181     {
182       if(_nodal_connec->getNumberOfComponents()!=1)
183         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184       if(_nodal_connec->getInfoOnComponent(0)!="")
185         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
186     }
187   else
188     if(_mesh_dim!=-1)
189       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190   if(_nodal_connec_index)
191     {
192       if(_nodal_connec_index->getNumberOfComponents()!=1)
193         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194       if(_nodal_connec_index->getInfoOnComponent(0)!="")
195         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
196     }
197   else
198     if(_mesh_dim!=-1)
199       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
200 }
201
202 /*!
203  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204  * then \a this mesh is most probably is writable, exchangeable and available for all
205  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206  * method thoroughly checks the nodal connectivity.
207  *  \param [in] eps - a not used parameter.
208  *  \throw If the mesh dimension is not set.
209  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
210  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211  *  \throw If the connectivity data array has more than one component.
212  *  \throw If the connectivity data array has a named component.
213  *  \throw If the connectivity index data array has more than one component.
214  *  \throw If the connectivity index data array has a named component.
215  *  \throw If number of nodes defining an element does not correspond to the type of element.
216  *  \throw If the nodal connectivity includes an invalid node id.
217  */
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
219 {
220   checkCoherency();
221   if(_mesh_dim==-1)
222     return ;
223   int meshDim=getMeshDimension();
224   int nbOfNodes=getNumberOfNodes();
225   int nbOfCells=getNumberOfCells();
226   const int *ptr=_nodal_connec->getConstPointer();
227   const int *ptrI=_nodal_connec_index->getConstPointer();
228   for(int i=0;i<nbOfCells;i++)
229     {
230       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231       if((int)cm.getDimension()!=meshDim)
232         {
233           std::ostringstream oss;
234           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235           throw INTERP_KERNEL::Exception(oss.str().c_str());
236         }
237       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
238       if(!cm.isDynamic())
239         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
240           {
241             std::ostringstream oss;
242             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
243             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244             throw INTERP_KERNEL::Exception(oss.str().c_str());
245           }
246       if(cm.isQuadratic() && cm.isDynamic() && meshDim == 2)
247         if (nbOfNodesInCell % 2 || nbOfNodesInCell < 4)
248           {
249             std::ostringstream oss;
250             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with quadratic type '" << cm.getRepr() << "' has " <<  nbOfNodesInCell;
251             oss << " nodes. This should be even, and greater or equal than 4!! Looks very bad!";
252             throw INTERP_KERNEL::Exception(oss.str().c_str());
253           }
254       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
255         {
256           int nodeId=*w;
257           if(nodeId>=0)
258             {
259               if(nodeId>=nbOfNodes)
260                 {
261                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes in the mesh !";
262                   throw INTERP_KERNEL::Exception(oss.str().c_str());
263                 }
264             }
265           else if(nodeId<-1)
266             {
267               std::ostringstream oss; oss << "Cell #" << i << " is built with node #" << nodeId << " in connectivity ! sounds bad !";
268               throw INTERP_KERNEL::Exception(oss.str().c_str());
269             }
270           else
271             {
272               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
273                 {
274                   std::ostringstream oss; oss << "Cell #" << i << " is built with node #-1 in connectivity ! sounds bad !";
275                   throw INTERP_KERNEL::Exception(oss.str().c_str());
276                 }
277             }
278         }
279     }
280 }
281
282
283 /*!
284  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
285  * then \a this mesh is most probably is writable, exchangeable and available for all
286  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
287  *  \param [in] eps - a not used parameter.
288  *  \throw If the mesh dimension is not set.
289  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
290  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
291  *  \throw If the connectivity data array has more than one component.
292  *  \throw If the connectivity data array has a named component.
293  *  \throw If the connectivity index data array has more than one component.
294  *  \throw If the connectivity index data array has a named component.
295  *  \throw If number of nodes defining an element does not correspond to the type of element.
296  *  \throw If the nodal connectivity includes an invalid node id.
297  */
298 void MEDCouplingUMesh::checkCoherency2(double eps) const
299 {
300   checkCoherency1(eps);
301 }
302
303 /*!
304  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
305  * elements contained in the mesh. For more info on the mesh dimension see
306  * \ref MEDCouplingUMeshPage.
307  *  \param [in] meshDim - a new mesh dimension.
308  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
309  */
310 void MEDCouplingUMesh::setMeshDimension(int meshDim)
311 {
312   if(meshDim<-1 || meshDim>3)
313     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
314   _mesh_dim=meshDim;
315   declareAsNew();
316 }
317
318 /*!
319  * Allocates memory to store an estimation of the given number of cells. The closer is the estimation to the number of cells effectively inserted,
320  * 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.
321  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
322  *
323  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
324  *
325  *  \if ENABLE_EXAMPLES
326  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
327  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
328  *  \endif
329  */
330 void MEDCouplingUMesh::allocateCells(int nbOfCells)
331 {
332   if(nbOfCells<0)
333     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
334   if(_nodal_connec_index)
335     {
336       _nodal_connec_index->decrRef();
337     }
338   if(_nodal_connec)
339     {
340       _nodal_connec->decrRef();
341     }
342   _nodal_connec_index=DataArrayInt::New();
343   _nodal_connec_index->reserve(nbOfCells+1);
344   _nodal_connec_index->pushBackSilent(0);
345   _nodal_connec=DataArrayInt::New();
346   _nodal_connec->reserve(2*nbOfCells);
347   _types.clear();
348   declareAsNew();
349 }
350
351 /*!
352  * Appends a cell to the connectivity array. For deeper understanding what is
353  * happening see \ref MEDCouplingUMeshNodalConnectivity.
354  *  \param [in] type - type of cell to add.
355  *  \param [in] size - number of nodes constituting this cell.
356  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
357  * 
358  *  \if ENABLE_EXAMPLES
359  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
360  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
361  *  \endif
362  */
363 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
364 {
365   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
366   if(_nodal_connec_index==0)
367     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
368   if((int)cm.getDimension()==_mesh_dim)
369     {
370       if(!cm.isDynamic())
371         if(size!=(int)cm.getNumberOfNodes())
372           {
373             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
374             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
375             throw INTERP_KERNEL::Exception(oss.str().c_str());
376           }
377       int idx=_nodal_connec_index->back();
378       int val=idx+size+1;
379       _nodal_connec_index->pushBackSilent(val);
380       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
381       _types.insert(type);
382     }
383   else
384     {
385       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
386       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
387       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
388       throw INTERP_KERNEL::Exception(oss.str().c_str());
389     }
390 }
391
392 /*!
393  * Compacts data arrays to release unused memory. This method is to be called after
394  * finishing cell insertion using \a this->insertNextCell().
395  * 
396  *  \if ENABLE_EXAMPLES
397  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
398  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
399  *  \endif
400  */
401 void MEDCouplingUMesh::finishInsertingCells()
402 {
403   _nodal_connec->pack();
404   _nodal_connec_index->pack();
405   _nodal_connec->declareAsNew();
406   _nodal_connec_index->declareAsNew();
407   updateTime();
408 }
409
410 /*!
411  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
412  * Useful for python users.
413  */
414 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
415 {
416   return new MEDCouplingUMeshCellIterator(this);
417 }
418
419 /*!
420  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
421  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
422  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
423  * Useful for python users.
424  */
425 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
426 {
427   if(!checkConsecutiveCellTypes())
428     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
429   return new MEDCouplingUMeshCellByTypeEntry(this);
430 }
431
432 /*!
433  * Returns a set of all cell types available in \a this mesh.
434  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
435  * \warning this method does not throw any exception even if \a this is not defined.
436  * \sa MEDCouplingUMesh::getAllGeoTypesSorted
437  */
438 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
439 {
440   return _types;
441 }
442
443 /*!
444  * This method returns the sorted list of geometric types in \a this.
445  * 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
446  * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
447  *
448  * \throw if connectivity in \a this is not correctly defined.
449  *  
450  * \sa MEDCouplingMesh::getAllGeoTypes
451  */
452 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
453 {
454   std::vector<INTERP_KERNEL::NormalizedCellType> ret;
455   checkConnectivityFullyDefined();
456   int nbOfCells(getNumberOfCells());
457   if(nbOfCells==0)
458     return ret;
459   if(getMeshLength()<1)
460     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
461   const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
462   ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
463   for(int i=1;i<nbOfCells;i++,ci++)
464     if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
465       ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
466   return ret;
467 }
468
469 /*!
470  * This method is a method that compares \a this and \a other.
471  * This method compares \b all attributes, even names and component names.
472  */
473 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
474 {
475   if(!other)
476     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
477   std::ostringstream oss; oss.precision(15);
478   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
479   if(!otherC)
480     {
481       reason="mesh given in input is not castable in MEDCouplingUMesh !";
482       return false;
483     }
484   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
485     return false;
486   if(_mesh_dim!=otherC->_mesh_dim)
487     {
488       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
489       reason=oss.str();
490       return false;
491     }
492   if(_types!=otherC->_types)
493     {
494       oss << "umesh geometric type mismatch :\nThis geometric types are :";
495       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
496         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
497       oss << "\nOther geometric types are :";
498       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
499         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
500       reason=oss.str();
501       return false;
502     }
503   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
504     if(_nodal_connec==0 || otherC->_nodal_connec==0)
505       {
506         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
507         return false;
508       }
509   if(_nodal_connec!=otherC->_nodal_connec)
510     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
511       {
512         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
513         return false;
514       }
515   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
516     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
517       {
518         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
519         return false;
520       }
521   if(_nodal_connec_index!=otherC->_nodal_connec_index)
522     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
523       {
524         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
525         return false;
526       }
527   return true;
528 }
529
530 /*!
531  * Checks if data arrays of this mesh (node coordinates, nodal
532  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
533  * not considered.
534  *  \param [in] other - the mesh to compare with.
535  *  \param [in] prec - precision value used to compare node coordinates.
536  *  \return bool - \a true if the two meshes are same.
537  */
538 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
539 {
540   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
541   if(!otherC)
542     return false;
543   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
544     return false;
545   if(_mesh_dim!=otherC->_mesh_dim)
546     return false;
547   if(_types!=otherC->_types)
548     return false;
549   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
550     if(_nodal_connec==0 || otherC->_nodal_connec==0)
551       return false;
552   if(_nodal_connec!=otherC->_nodal_connec)
553     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
554       return false;
555   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
556     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
557       return false;
558   if(_nodal_connec_index!=otherC->_nodal_connec_index)
559     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
560       return false;
561   return true;
562 }
563
564 /*!
565  * Checks if \a this and \a other meshes are geometrically equivalent with high
566  * probability, else an exception is thrown. The meshes are considered equivalent if
567  * (1) meshes contain the same number of nodes and the same number of elements of the
568  * same types (2) three cells of the two meshes (first, last and middle) are based
569  * on coincident nodes (with a specified precision).
570  *  \param [in] other - the mesh to compare with.
571  *  \param [in] prec - the precision used to compare nodes of the two meshes.
572  *  \throw If the two meshes do not match.
573  */
574 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
575 {
576   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
577   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
578   if(!otherC)
579     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
580 }
581
582 /*!
583  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
584  * cells each node belongs to.
585  * \warning For speed reasons, this method does not check if node ids in the nodal
586  *          connectivity correspond to the size of node coordinates array.
587  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
588  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
589  *        dividing cell ids in \a revNodal into groups each referring to one
590  *        node. Its every element (except the last one) is an index pointing to the
591  *         first id of a group of cells. For example cells sharing the node #1 are 
592  *        described by following range of indices: 
593  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
594  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
595  *        Number of cells sharing the *i*-th node is
596  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
597  * \throw If the coordinates array is not set.
598  * \throw If the nodal connectivity of cells is not defined.
599  * 
600  * \if ENABLE_EXAMPLES
601  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
602  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
603  * \endif
604  */
605 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
606 {
607   checkFullyDefined();
608   int nbOfNodes=getNumberOfNodes();
609   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
610   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
611   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
612   const int *conn=_nodal_connec->getConstPointer();
613   const int *connIndex=_nodal_connec_index->getConstPointer();
614   int nbOfCells=getNumberOfCells();
615   int nbOfEltsInRevNodal=0;
616   for(int eltId=0;eltId<nbOfCells;eltId++)
617     {
618       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
619       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
620       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
621         if(*iter>=0)//for polyhedrons
622           {
623             nbOfEltsInRevNodal++;
624             revNodalIndxPtr[(*iter)+1]++;
625           }
626     }
627   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
628   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
629   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
630   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
631   for(int eltId=0;eltId<nbOfCells;eltId++)
632     {
633       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
634       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
635       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
636         if(*iter>=0)//for polyhedrons
637           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
638     }
639 }
640
641 /// @cond INTERNAL
642
643 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
644 {
645   return id;
646 }
647
648 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
649 {
650   if(!compute)
651     return id+1;
652   else
653     {
654       if(cm.getOrientationStatus(nb,conn1,conn2))
655         return id+1;
656       else
657         return -(id+1);
658     }
659 }
660
661 class MinusOneSonsGenerator
662 {
663 public:
664   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
665   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
666   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
667   static const int DELTA=1;
668 private:
669   const INTERP_KERNEL::CellModel& _cm;
670 };
671
672 class MinusOneSonsGeneratorBiQuadratic
673 {
674 public:
675   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
676   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
677   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
678   static const int DELTA=1;
679 private:
680   const INTERP_KERNEL::CellModel& _cm;
681 };
682
683 class MinusTwoSonsGenerator
684 {
685 public:
686   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
687   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
688   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
689   static const int DELTA=2;
690 private:
691   const INTERP_KERNEL::CellModel& _cm;
692 };
693
694 /// @endcond
695
696 /*!
697  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
698  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
699  * describing correspondence between cells of \a this and the result meshes are
700  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
701  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
702  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
703  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
704  * \warning For speed reasons, this method does not check if node ids in the nodal
705  *          connectivity correspond to the size of node coordinates array.
706  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
707  *          to write this mesh to the MED file, its cells must be sorted using
708  *          sortCellsInMEDFileFrmt().
709  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
710  *         each cell of \a this mesh.
711  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
712  *        dividing cell ids in \a desc into groups each referring to one
713  *        cell of \a this mesh. Its every element (except the last one) is an index
714  *        pointing to the first id of a group of cells. For example cells of the
715  *        result mesh bounding the cell #1 of \a this mesh are described by following
716  *        range of indices:
717  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
718  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
719  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
720  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
721  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
722  *         by each cell of the result mesh.
723  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
724  *        in the result mesh,
725  *        dividing cell ids in \a revDesc into groups each referring to one
726  *        cell of the result mesh the same way as \a descIndx divides \a desc.
727  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
728  *        delete this mesh using decrRef() as it is no more needed.
729  *  \throw If the coordinates array is not set.
730  *  \throw If the nodal connectivity of cells is node defined.
731  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
732  *         revDescIndx == NULL.
733  * 
734  *  \if ENABLE_EXAMPLES
735  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
736  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
737  *  \endif
738  * \sa buildDescendingConnectivity2()
739  */
740 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
741 {
742   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
743 }
744
745 /*!
746  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
747  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
748  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
749  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
750  * \sa MEDCouplingUMesh::buildDescendingConnectivity
751  */
752 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
753 {
754   checkFullyDefined();
755   if(getMeshDimension()!=3)
756     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
757   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
758 }
759
760 /*!
761  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
762  * this->getMeshDimension(), that bound cells of \a this mesh. In
763  * addition arrays describing correspondence between cells of \a this and the result
764  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
765  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
766  *  mesh. This method differs from buildDescendingConnectivity() in that apart
767  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
768  * result meshes. So a positive id means that order of nodes in corresponding cells
769  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
770  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
771  * i.e. cell ids are one-based.
772  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
773  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
774  * \warning For speed reasons, this method does not check if node ids in the nodal
775  *          connectivity correspond to the size of node coordinates array.
776  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
777  *          to write this mesh to the MED file, its cells must be sorted using
778  *          sortCellsInMEDFileFrmt().
779  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
780  *         each cell of \a this mesh.
781  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
782  *        dividing cell ids in \a desc into groups each referring to one
783  *        cell of \a this mesh. Its every element (except the last one) is an index
784  *        pointing to the first id of a group of cells. For example cells of the
785  *        result mesh bounding the cell #1 of \a this mesh are described by following
786  *        range of indices:
787  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
788  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
789  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
790  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
791  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
792  *         by each cell of the result mesh.
793  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
794  *        in the result mesh,
795  *        dividing cell ids in \a revDesc into groups each referring to one
796  *        cell of the result mesh the same way as \a descIndx divides \a desc.
797  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
798  *        shares the node coordinates array with \a this mesh. The caller is to
799  *        delete this mesh using decrRef() as it is no more needed.
800  *  \throw If the coordinates array is not set.
801  *  \throw If the nodal connectivity of cells is node defined.
802  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
803  *         revDescIndx == NULL.
804  * 
805  *  \if ENABLE_EXAMPLES
806  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
807  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
808  *  \endif
809  * \sa buildDescendingConnectivity()
810  */
811 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
812 {
813   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
814 }
815
816 /*!
817  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
818  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
819  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
820  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
821  *
822  * \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
823  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
824  * \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.
825  */
826 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
827 {
828   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
829   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
831   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
832   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
833   meshDM1=0;
834   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
835 }
836
837 /*!
838  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
839  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
840  * excluding a set of meshdim-1 cells in input descending connectivity.
841  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
842  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
843  * The neighbor cells of cell having id 'cellId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
844  *
845  * \param [in] desc descending connectivity array.
846  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
847  * \param [in] revDesc reverse descending connectivity array.
848  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
849  * \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
850  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
851  * \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.
852  */
853 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
854                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx)
855 {
856   if(!desc || !descIndx || !revDesc || !revDescIndx)
857     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
858   const int *descPtr=desc->getConstPointer();
859   const int *descIPtr=descIndx->getConstPointer();
860   const int *revDescPtr=revDesc->getConstPointer();
861   const int *revDescIPtr=revDescIndx->getConstPointer();
862   //
863   int nbCells=descIndx->getNumberOfTuples()-1;
864   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
865   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
866   int *out1Ptr=out1->getPointer();
867   *out1Ptr++=0;
868   out0->reserve(desc->getNumberOfTuples());
869   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
870     {
871       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
872         {
873           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
874           s.erase(i);
875           out0->insertAtTheEnd(s.begin(),s.end());
876         }
877       *out1Ptr=out0->getNumberOfTuples();
878     }
879   neighbors=out0.retn();
880   neighborsIndx=out1.retn();
881 }
882
883 /*!
884  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
885  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
886  * This method lists node by node in \b this which are its neighbors. To compute the result only connectivities are considered.
887  * The neighbor nodes of node having id 'nodeId' are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
888  *
889  * \param [out] neighbors is an array storing all the neighbors of all nodes in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
890  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
891  * \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.
892  */
893 void MEDCouplingUMesh::computeNeighborsOfNodes(DataArrayInt *&neighbors, DataArrayInt *&neighborsIdx) const
894 {
895   checkFullyDefined();
896   int mdim(getMeshDimension()),nbNodes(getNumberOfNodes());
897   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descIndx(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescIndx(DataArrayInt::New());
898   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh1D;
899   switch(mdim)
900   {
901     case 3:
902       {
903         mesh1D=explode3DMeshTo1D(desc,descIndx,revDesc,revDescIndx);
904         break;
905       }
906     case 2:
907       {
908         mesh1D=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
909         break;
910       }
911     case 1:
912       {
913         mesh1D=const_cast<MEDCouplingUMesh *>(this);
914         mesh1D->incrRef();
915         break;
916       }
917     default:
918       {
919         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computeNeighborsOfNodes : Mesh dimension supported are [3,2,1] !");
920       }
921   }
922   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=0; revDescIndx=0;
923   mesh1D->getReverseNodalConnectivity(desc,descIndx);
924   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0(DataArrayInt::New());
925   ret0->alloc(desc->getNumberOfTuples(),1);
926   int *r0Pt(ret0->getPointer());
927   const int *c1DPtr(mesh1D->getNodalConnectivity()->begin()),*rn(desc->begin()),*rni(descIndx->begin());
928   for(int i=0;i<nbNodes;i++,rni++)
929     {
930       for(const int *oneDCellIt=rn+rni[0];oneDCellIt!=rn+rni[1];oneDCellIt++)
931         *r0Pt++=c1DPtr[3*(*oneDCellIt)+1]==i?c1DPtr[3*(*oneDCellIt)+2]:c1DPtr[3*(*oneDCellIt)+1];
932     }
933   neighbors=ret0.retn();
934   neighborsIdx=descIndx.retn();
935 }
936
937 /// @cond INTERNAL
938
939 /*!
940  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
941  * For speed reasons no check of this will be done.
942  */
943 template<class SonsGenerator>
944 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
945 {
946   if(!desc || !descIndx || !revDesc || !revDescIndx)
947     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
948   checkConnectivityFullyDefined();
949   int nbOfCells=getNumberOfCells();
950   int nbOfNodes=getNumberOfNodes();
951   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
952   int *revNodalIndxPtr=revNodalIndx->getPointer();
953   const int *conn=_nodal_connec->getConstPointer();
954   const int *connIndex=_nodal_connec_index->getConstPointer();
955   std::string name="Mesh constituent of "; name+=getName();
956   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
957   ret->setCoords(getCoords());
958   ret->allocateCells(2*nbOfCells);
959   descIndx->alloc(nbOfCells+1,1);
960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
961   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
962   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
963     {
964       int pos=connIndex[eltId];
965       int posP1=connIndex[eltId+1];
966       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
967       SonsGenerator sg(cm);
968       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
969       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
970       for(unsigned i=0;i<nbOfSons;i++)
971         {
972           INTERP_KERNEL::NormalizedCellType cmsId;
973           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
974           for(unsigned k=0;k<nbOfNodesSon;k++)
975             if(tmp[k]>=0)
976               revNodalIndxPtr[tmp[k]+1]++;
977           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
978           revDesc2->pushBackSilent(eltId);
979         }
980       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
981     }
982   int nbOfCellsM1=ret->getNumberOfCells();
983   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
984   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
985   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
986   int *revNodalPtr=revNodal->getPointer();
987   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
988   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
989   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
990     {
991       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
992       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
993       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
994         if(*iter>=0)//for polyhedrons
995           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
996     }
997   //
998   DataArrayInt *commonCells=0,*commonCellsI=0;
999   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
1000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1001   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
1002   int newNbOfCellsM1=-1;
1003   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
1004                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
1005   std::vector<bool> isImpacted(nbOfCellsM1,false);
1006   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
1007     for(int work2=work[0];work2!=work[1];work2++)
1008       isImpacted[commonCellsPtr[work2]]=true;
1009   const int *o2nM1Ptr=o2nM1->getConstPointer();
1010   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
1011   const int *n2oM1Ptr=n2oM1->getConstPointer();
1012   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
1013   ret2->copyTinyInfoFrom(this);
1014   desc->alloc(descIndx->back(),1);
1015   int *descPtr=desc->getPointer();
1016   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
1017   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
1018     {
1019       if(!isImpacted[i])
1020         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1021       else
1022         {
1023           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
1024             {
1025               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
1026               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
1027             }
1028           else
1029             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
1030         }
1031     }
1032   revDesc->reserve(newNbOfCellsM1);
1033   revDescIndx->alloc(newNbOfCellsM1+1,1);
1034   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
1035   const int *revDesc2Ptr=revDesc2->getConstPointer();
1036   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
1037     {
1038       int oldCellIdM1=n2oM1Ptr[i];
1039       if(!isImpacted[oldCellIdM1])
1040         {
1041           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
1042           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
1043         }
1044       else
1045         {
1046           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
1047             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
1048           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
1049           commonCellsIPtr++;
1050         }
1051     }
1052   //
1053   return ret2.retn();
1054 }
1055
1056 struct MEDCouplingAccVisit
1057 {
1058   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
1059   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
1060   int _new_nb_of_nodes;
1061 };
1062
1063 /// @endcond
1064
1065 /*!
1066  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1067  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1068  * array of cell ids. Pay attention that after conversion all algorithms work slower
1069  * with \a this mesh than before conversion. <br> If an exception is thrown during the
1070  * conversion due presence of invalid ids in the array of cells to convert, as a
1071  * result \a this mesh contains some already converted elements. In this case the 2D
1072  * mesh remains valid but 3D mesh becomes \b inconsistent!
1073  *  \warning This method can significantly modify the order of geometric types in \a this,
1074  *          hence, to write this mesh to the MED file, its cells must be sorted using
1075  *          sortCellsInMEDFileFrmt().
1076  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1077  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1078  *         cellIdsToConvertBg.
1079  *  \throw If the coordinates array is not set.
1080  *  \throw If the nodal connectivity of cells is node defined.
1081  *  \throw If dimension of \a this mesh is not either 2 or 3.
1082  *
1083  *  \if ENABLE_EXAMPLES
1084  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1085  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
1086  *  \endif
1087  */
1088 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1089 {
1090   checkFullyDefined();
1091   int dim=getMeshDimension();
1092   if(dim<2 || dim>3)
1093     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1094   int nbOfCells(getNumberOfCells());
1095   if(dim==2)
1096     {
1097       const int *connIndex=_nodal_connec_index->getConstPointer();
1098       int *conn=_nodal_connec->getPointer();
1099       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1100         {
1101           if(*iter>=0 && *iter<nbOfCells)
1102             {
1103               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1104               if(!cm.isQuadratic())
1105                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1106               else
1107                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1108             }
1109           else
1110             {
1111               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1112               oss << " in range [0," << nbOfCells << ") !";
1113               throw INTERP_KERNEL::Exception(oss.str().c_str());
1114             }
1115         }
1116     }
1117   else
1118     {
1119       int *connIndex(_nodal_connec_index->getPointer());
1120       const int *connOld(_nodal_connec->getConstPointer());
1121       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1122       std::vector<bool> toBeDone(nbOfCells,false);
1123       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1124         {
1125           if(*iter>=0 && *iter<nbOfCells)
1126             toBeDone[*iter]=true;
1127           else
1128             {
1129               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1130               oss << " in range [0," << nbOfCells << ") !";
1131               throw INTERP_KERNEL::Exception(oss.str().c_str());
1132             }
1133         }
1134       for(int cellId=0;cellId<nbOfCells;cellId++)
1135         {
1136           int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1137           int lgthOld(posP1-pos-1);
1138           if(toBeDone[cellId])
1139             {
1140               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1141               unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1142               int *tmp(new int[nbOfFaces*lgthOld+1]);
1143               int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1144               for(unsigned j=0;j<nbOfFaces;j++)
1145                 {
1146                   INTERP_KERNEL::NormalizedCellType type;
1147                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1148                   work+=offset;
1149                   *work++=-1;
1150                 }
1151               std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1152               connNew->pushBackValsSilent(tmp,tmp+newLgth);
1153               connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1154               delete [] tmp;
1155             }
1156           else
1157             {
1158               connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1159               connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1160             }
1161         }
1162       setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1163     }
1164   computeTypes();
1165 }
1166
1167 /*!
1168  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1169  * polyhedrons (if \a this is a 3D mesh).
1170  *  \warning As this method is purely for user-friendliness and no optimization is
1171  *          done to avoid construction of a useless vector, this method can be costly
1172  *          in memory.
1173  *  \throw If the coordinates array is not set.
1174  *  \throw If the nodal connectivity of cells is node defined.
1175  *  \throw If dimension of \a this mesh is not either 2 or 3.
1176  */
1177 void MEDCouplingUMesh::convertAllToPoly()
1178 {
1179   int nbOfCells=getNumberOfCells();
1180   std::vector<int> cellIds(nbOfCells);
1181   for(int i=0;i<nbOfCells;i++)
1182     cellIds[i]=i;
1183   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1184 }
1185
1186 /*!
1187  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1188  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1189  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1190  * base facet of the volume and the second half of nodes describes an opposite facet
1191  * having the same number of nodes as the base one. This method converts such
1192  * connectivity to a valid polyhedral format where connectivity of each facet is
1193  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1194  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1195  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1196  * a correct orientation of the first facet of a polyhedron, else orientation of a
1197  * corrected cell is reverse.<br>
1198  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1199  * it releases the user from boring description of polyhedra connectivity in the valid
1200  * format.
1201  *  \throw If \a this->getMeshDimension() != 3.
1202  *  \throw If \a this->getSpaceDimension() != 3.
1203  *  \throw If the nodal connectivity of cells is not defined.
1204  *  \throw If the coordinates array is not set.
1205  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1206  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1207  *
1208  *  \if ENABLE_EXAMPLES
1209  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1210  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1211  *  \endif
1212  */
1213 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1214 {
1215   checkFullyDefined();
1216   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1217     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1218   int nbOfCells=getNumberOfCells();
1219   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1220   newCi->alloc(nbOfCells+1,1);
1221   int *newci=newCi->getPointer();
1222   const int *ci=_nodal_connec_index->getConstPointer();
1223   const int *c=_nodal_connec->getConstPointer();
1224   newci[0]=0;
1225   for(int i=0;i<nbOfCells;i++)
1226     {
1227       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1228       if(type==INTERP_KERNEL::NORM_POLYHED)
1229         {
1230           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1231             {
1232               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1233               throw INTERP_KERNEL::Exception(oss.str().c_str());
1234             }
1235           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1236           if(n2%2!=0)
1237             {
1238               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 !";
1239               throw INTERP_KERNEL::Exception(oss.str().c_str());
1240             }
1241           int n1=(int)(n2/2);
1242           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)
1243         }
1244       else
1245         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1246     }
1247   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1248   newC->alloc(newci[nbOfCells],1);
1249   int *newc=newC->getPointer();
1250   for(int i=0;i<nbOfCells;i++)
1251     {
1252       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1253       if(type==INTERP_KERNEL::NORM_POLYHED)
1254         {
1255           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1256           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1257           *newc++=-1;
1258           for(std::size_t j=0;j<n1;j++)
1259             {
1260               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1261               newc[n1+5*j]=-1;
1262               newc[n1+5*j+1]=c[ci[i]+1+j];
1263               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1264               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1265               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1266             }
1267           newc+=n1*6;
1268         }
1269       else
1270         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1271     }
1272   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1273   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1274 }
1275
1276
1277 /*!
1278  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1279  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1280  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1281  *          to write this mesh to the MED file, its cells must be sorted using
1282  *          sortCellsInMEDFileFrmt().
1283  * \return \c true if at least one cell has been converted, \c false else. In the
1284  *         last case the nodal connectivity remains unchanged.
1285  * \throw If the coordinates array is not set.
1286  * \throw If the nodal connectivity of cells is not defined.
1287  * \throw If \a this->getMeshDimension() < 0.
1288  */
1289 bool MEDCouplingUMesh::unPolyze()
1290 {
1291   checkFullyDefined();
1292   int mdim=getMeshDimension();
1293   if(mdim<0)
1294     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1295   if(mdim<=1)
1296     return false;
1297   int nbOfCells=getNumberOfCells();
1298   if(nbOfCells<1)
1299     return false;
1300   int initMeshLgth=getMeshLength();
1301   int *conn=_nodal_connec->getPointer();
1302   int *index=_nodal_connec_index->getPointer();
1303   int posOfCurCell=0;
1304   int newPos=0;
1305   int lgthOfCurCell;
1306   bool ret=false;
1307   for(int i=0;i<nbOfCells;i++)
1308     {
1309       lgthOfCurCell=index[i+1]-posOfCurCell;
1310       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1311       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1312       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1313       int newLgth;
1314       if(cm.isDynamic())
1315         {
1316           switch(cm.getDimension())
1317           {
1318             case 2:
1319               {
1320                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1321                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1322                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1323                 break;
1324               }
1325             case 3:
1326               {
1327                 int nbOfFaces,lgthOfPolyhConn;
1328                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1329                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1330                 break;
1331               }
1332             case 1:
1333               {
1334                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1335                 break;
1336               }
1337           }
1338           ret=ret || (newType!=type);
1339           conn[newPos]=newType;
1340           newPos+=newLgth+1;
1341           posOfCurCell=index[i+1];
1342           index[i+1]=newPos;
1343         }
1344       else
1345         {
1346           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1347           newPos+=lgthOfCurCell;
1348           posOfCurCell+=lgthOfCurCell;
1349           index[i+1]=newPos;
1350         }
1351     }
1352   if(newPos!=initMeshLgth)
1353     _nodal_connec->reAlloc(newPos);
1354   if(ret)
1355     computeTypes();
1356   return ret;
1357 }
1358
1359 /*!
1360  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1361  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1362  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1363  *
1364  * \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 
1365  *             precision.
1366  */
1367 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1368 {
1369   checkFullyDefined();
1370   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1371     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1372   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1373   coords->recenterForMaxPrecision(eps);
1374   //
1375   int nbOfCells=getNumberOfCells();
1376   const int *conn=_nodal_connec->getConstPointer();
1377   const int *index=_nodal_connec_index->getConstPointer();
1378   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1379   connINew->alloc(nbOfCells+1,1);
1380   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1381   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1382   bool changed=false;
1383   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1384     {
1385       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1386         {
1387           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1388           changed=true;
1389         }
1390       else
1391         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1392       *connINewPtr=connNew->getNumberOfTuples();
1393     }
1394   if(changed)
1395     setConnectivity(connNew,connINew,false);
1396 }
1397
1398 /*!
1399  * This method returns all node ids used in the connectivity of \b this. The data array returned has to be dealt by the caller.
1400  * The returned node ids are sorted ascendingly. This method is close to MEDCouplingUMesh::getNodeIdsInUse except
1401  * the format of the returned DataArrayInt instance.
1402  * 
1403  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1404  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1405  */
1406 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1407 {
1408   checkConnectivityFullyDefined();
1409   int nbOfCells=getNumberOfCells();
1410   const int *connIndex=_nodal_connec_index->getConstPointer();
1411   const int *conn=_nodal_connec->getConstPointer();
1412   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1413   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1414   std::vector<bool> retS(maxElt,false);
1415   for(int i=0;i<nbOfCells;i++)
1416     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1417       if(conn[j]>=0)
1418         retS[conn[j]]=true;
1419   int sz=0;
1420   for(int i=0;i<maxElt;i++)
1421     if(retS[i])
1422       sz++;
1423   DataArrayInt *ret=DataArrayInt::New();
1424   ret->alloc(sz,1);
1425   int *retPtr=ret->getPointer();
1426   for(int i=0;i<maxElt;i++)
1427     if(retS[i])
1428       *retPtr++=i;
1429   return ret;
1430 }
1431
1432 /*!
1433  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1434  * \sa MEDCouplingUMesh::getNodeIdsInUse, areAllNodesFetched
1435  */
1436 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1437 {
1438   int nbOfNodes((int)nodeIdsInUse.size()),nbOfCells(getNumberOfCells());
1439   const int *connIndex(_nodal_connec_index->getConstPointer()),*conn(_nodal_connec->getConstPointer());
1440   for(int i=0;i<nbOfCells;i++)
1441     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1442       if(conn[j]>=0)
1443         {
1444           if(conn[j]<nbOfNodes)
1445             nodeIdsInUse[conn[j]]=true;
1446           else
1447             {
1448               std::ostringstream oss; oss << "MEDCouplingUMesh::computeNodeIdsAlg : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1449               throw INTERP_KERNEL::Exception(oss.str().c_str());
1450             }
1451         }
1452 }
1453
1454 /*!
1455  * Finds nodes not used in any cell and returns an array giving a new id to every node
1456  * by excluding the unused nodes, for which the array holds -1. The result array is
1457  * a mapping in "Old to New" mode. 
1458  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1459  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1460  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1461  *          if the node is unused or a new id else. The caller is to delete this
1462  *          array using decrRef() as it is no more needed.  
1463  *  \throw If the coordinates array is not set.
1464  *  \throw If the nodal connectivity of cells is not defined.
1465  *  \throw If the nodal connectivity includes an invalid id.
1466  *
1467  *  \if ENABLE_EXAMPLES
1468  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1469  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1470  *  \endif
1471  * \sa computeFetchedNodeIds, computeNodeIdsAlg()
1472  */
1473 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1474 {
1475   nbrOfNodesInUse=-1;
1476   int nbOfNodes(getNumberOfNodes());
1477   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1478   ret->alloc(nbOfNodes,1);
1479   int *traducer=ret->getPointer();
1480   std::fill(traducer,traducer+nbOfNodes,-1);
1481   int nbOfCells=getNumberOfCells();
1482   const int *connIndex=_nodal_connec_index->getConstPointer();
1483   const int *conn=_nodal_connec->getConstPointer();
1484   for(int i=0;i<nbOfCells;i++)
1485     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1486       if(conn[j]>=0)
1487         {
1488           if(conn[j]<nbOfNodes)
1489             traducer[conn[j]]=1;
1490           else
1491             {
1492               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1493               throw INTERP_KERNEL::Exception(oss.str().c_str());
1494             }
1495         }
1496   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1497   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1498   return ret.retn();
1499 }
1500
1501 /*!
1502  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1503  * For each cell in \b this the number of nodes constituting cell is computed.
1504  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1505  * So for pohyhedrons some nodes can be counted several times in the returned result.
1506  * 
1507  * \return a newly allocated array
1508  * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1509  */
1510 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1511 {
1512   checkConnectivityFullyDefined();
1513   int nbOfCells=getNumberOfCells();
1514   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1515   ret->alloc(nbOfCells,1);
1516   int *retPtr=ret->getPointer();
1517   const int *conn=getNodalConnectivity()->getConstPointer();
1518   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1519   for(int i=0;i<nbOfCells;i++,retPtr++)
1520     {
1521       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1522         *retPtr=connI[i+1]-connI[i]-1;
1523       else
1524         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1525     }
1526   return ret.retn();
1527 }
1528
1529 /*!
1530  * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1531  * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1532  *
1533  * \return DataArrayInt * - new object to be deallocated by the caller.
1534  * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1535  */
1536 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1537 {
1538   checkConnectivityFullyDefined();
1539   int nbOfCells=getNumberOfCells();
1540   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1541   ret->alloc(nbOfCells,1);
1542   int *retPtr=ret->getPointer();
1543   const int *conn=getNodalConnectivity()->getConstPointer();
1544   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1545   for(int i=0;i<nbOfCells;i++,retPtr++)
1546     {
1547       std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1548       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1549         *retPtr=(int)s.size();
1550       else
1551         {
1552           s.erase(-1);
1553           *retPtr=(int)s.size();
1554         }
1555     }
1556   return ret.retn();
1557 }
1558
1559 /*!
1560  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1561  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1562  * 
1563  * \return a newly allocated array
1564  */
1565 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1566 {
1567   checkConnectivityFullyDefined();
1568   int nbOfCells=getNumberOfCells();
1569   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1570   ret->alloc(nbOfCells,1);
1571   int *retPtr=ret->getPointer();
1572   const int *conn=getNodalConnectivity()->getConstPointer();
1573   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1574   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1575     {
1576       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1577       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1578     }
1579   return ret.retn();
1580 }
1581
1582 /*!
1583  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1584  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1585  * array mean that the corresponding old node is no more used. 
1586  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1587  *           this->getNumberOfNodes() before call of this method. The caller is to
1588  *           delete this array using decrRef() as it is no more needed. 
1589  *  \throw If the coordinates array is not set.
1590  *  \throw If the nodal connectivity of cells is not defined.
1591  *  \throw If the nodal connectivity includes an invalid id.
1592  *  \sa areAllNodesFetched
1593  *
1594  *  \if ENABLE_EXAMPLES
1595  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1596  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1597  *  \endif
1598  */
1599 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1600 {
1601   return MEDCouplingPointSet::zipCoordsTraducer();
1602 }
1603
1604 /*!
1605  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1606  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1607  */
1608 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1609 {
1610   switch(compType)
1611   {
1612     case 0:
1613       return AreCellsEqual0(conn,connI,cell1,cell2);
1614     case 1:
1615       return AreCellsEqual1(conn,connI,cell1,cell2);
1616     case 2:
1617       return AreCellsEqual2(conn,connI,cell1,cell2);
1618     case 3:
1619       return AreCellsEqual3(conn,connI,cell1,cell2);
1620     case 7:
1621       return AreCellsEqual7(conn,connI,cell1,cell2);
1622   }
1623   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1624 }
1625
1626 /*!
1627  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1628  */
1629 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1630 {
1631   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1632     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1633   return 0;
1634 }
1635
1636 /*!
1637  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1638  */
1639 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1640 {
1641   int sz=connI[cell1+1]-connI[cell1];
1642   if(sz==connI[cell2+1]-connI[cell2])
1643     {
1644       if(conn[connI[cell1]]==conn[connI[cell2]])
1645         {
1646           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1647           unsigned dim=cm.getDimension();
1648           if(dim!=3)
1649             {
1650               if(dim!=1)
1651                 {
1652                   int sz1=2*(sz-1);
1653                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1654                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1655                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1656                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1657                   return work!=tmp+sz1?1:0;
1658                 }
1659               else
1660                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1661             }
1662           else
1663             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1664         }
1665     }
1666   return 0;
1667 }
1668
1669 /*!
1670  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1671  */
1672 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1673 {
1674   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1675     {
1676       if(conn[connI[cell1]]==conn[connI[cell2]])
1677         {
1678           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1679           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1680           return s1==s2?1:0;
1681         }
1682     }
1683   return 0;
1684 }
1685
1686 /*!
1687  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1688  */
1689 int MEDCouplingUMesh::AreCellsEqual3(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       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1694       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1695       return s1==s2?1:0;
1696     }
1697   return 0;
1698 }
1699
1700 /*!
1701  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1702  */
1703 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1704 {
1705   int sz=connI[cell1+1]-connI[cell1];
1706   if(sz==connI[cell2+1]-connI[cell2])
1707     {
1708       if(conn[connI[cell1]]==conn[connI[cell2]])
1709         {
1710           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1711           unsigned dim=cm.getDimension();
1712           if(dim!=3)
1713             {
1714               if(dim!=1)
1715                 {
1716                   int sz1=2*(sz-1);
1717                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1718                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1719                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1720                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1721                   if(work!=tmp+sz1)
1722                     return 1;
1723                   else
1724                     {
1725                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1726                       std::reverse_iterator<int *> it2((int *)tmp);
1727                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1728                         return 2;
1729                       else
1730                         return 0;
1731                     }
1732
1733                   return work!=tmp+sz1?1:0;
1734                 }
1735               else
1736                 {//case of SEG2 and SEG3
1737                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1738                     return 1;
1739                   if(!cm.isQuadratic())
1740                     {
1741                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1742                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1743                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1744                         return 2;
1745                       return 0;
1746                     }
1747                   else
1748                     {
1749                       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])
1750                         return 2;
1751                       return 0;
1752                     }
1753                 }
1754             }
1755           else
1756             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1757         }
1758     }
1759   return 0;
1760 }
1761
1762 /*!
1763  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1764  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1765  * and result remains unchanged.
1766  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1767  * If in 'candidates' pool -1 value is considered as an empty value.
1768  * WARNING this method returns only ONE set of result !
1769  */
1770 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1771 {
1772   if(candidates.size()<1)
1773     return false;
1774   bool ret=false;
1775   std::vector<int>::const_iterator iter=candidates.begin();
1776   int start=(*iter++);
1777   for(;iter!=candidates.end();iter++)
1778     {
1779       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1780       if(status!=0)
1781         {
1782           if(!ret)
1783             {
1784               result->pushBackSilent(start);
1785               ret=true;
1786             }
1787           if(status==1)
1788             result->pushBackSilent(*iter);
1789           else
1790             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1791         }
1792     }
1793   return ret;
1794 }
1795
1796 /*!
1797  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1798  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1799  *
1800  * \param [in] compType input specifying the technique used to compare cells each other.
1801  *   - 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.
1802  *   - 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)
1803  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1804  *   - 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
1805  * can be used for users not sensitive to orientation of cell
1806  * \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.
1807  * \param [out] commonCells
1808  * \param [out] commonCellsI
1809  * \return the correspondance array old to new in a newly allocated array.
1810  * 
1811  */
1812 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1813 {
1814   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1815   getReverseNodalConnectivity(revNodal,revNodalI);
1816   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1817 }
1818
1819 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1820                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr)
1821 {
1822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1823   int nbOfCells=nodalI->getNumberOfTuples()-1;
1824   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1825   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1826   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1827   std::vector<bool> isFetched(nbOfCells,false);
1828   if(startCellId==0)
1829     {
1830       for(int i=0;i<nbOfCells;i++)
1831         {
1832           if(!isFetched[i])
1833             {
1834               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1835               std::vector<int> v,v2;
1836               if(connOfNode!=connPtr+connIPtr[i+1])
1837                 {
1838                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1839                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1840                   connOfNode++;
1841                 }
1842               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1843                 if(*connOfNode>=0)
1844                   {
1845                     v=v2;
1846                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1847                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1848                     v2.resize(std::distance(v2.begin(),it));
1849                   }
1850               if(v2.size()>1)
1851                 {
1852                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1853                     {
1854                       int pos=commonCellsI->back();
1855                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1856                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1857                         isFetched[*it]=true;
1858                     }
1859                 }
1860             }
1861         }
1862     }
1863   else
1864     {
1865       for(int i=startCellId;i<nbOfCells;i++)
1866         {
1867           if(!isFetched[i])
1868             {
1869               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1870               std::vector<int> v,v2;
1871               if(connOfNode!=connPtr+connIPtr[i+1])
1872                 {
1873                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1874                   connOfNode++;
1875                 }
1876               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1877                 if(*connOfNode>=0)
1878                   {
1879                     v=v2;
1880                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1881                     v2.resize(std::distance(v2.begin(),it));
1882                   }
1883               if(v2.size()>1)
1884                 {
1885                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1886                     {
1887                       int pos=commonCellsI->back();
1888                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1889                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1890                         isFetched[*it]=true;
1891                     }
1892                 }
1893             }
1894         }
1895     }
1896   commonCellsArr=commonCells.retn();
1897   commonCellsIArr=commonCellsI.retn();
1898 }
1899
1900 /*!
1901  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1902  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1903  * than \a other->getNumberOfCells() in the returned array means that there is no
1904  * corresponding cell in \a this mesh.
1905  * It is expected that \a this and \a other meshes share the same node coordinates
1906  * array, if it is not so an exception is thrown. 
1907  *  \param [in] other - the mesh to compare with.
1908  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1909  *         valid values [0,1,2], see zipConnectivityTraducer().
1910  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1911  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1912  *         values. The caller is to delete this array using
1913  *         decrRef() as it is no more needed.
1914  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1915  *         mesh.
1916  *
1917  *  \if ENABLE_EXAMPLES
1918  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1919  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1920  *  \endif
1921  *  \sa checkDeepEquivalOnSameNodesWith()
1922  *  \sa checkGeoEquivalWith()
1923  */
1924 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1925 {
1926   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1927   int nbOfCells=getNumberOfCells();
1928   static const int possibleCompType[]={0,1,2};
1929   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1930     {
1931       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1932       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1933       oss << " !";
1934       throw INTERP_KERNEL::Exception(oss.str().c_str());
1935     }
1936   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1937   arr=o2n->substr(nbOfCells);
1938   arr->setName(other->getName());
1939   int tmp;
1940   if(other->getNumberOfCells()==0)
1941     return true;
1942   return arr->getMaxValue(tmp)<nbOfCells;
1943 }
1944
1945 /*!
1946  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1947  * This method tries to determine if \b other is fully included in \b this.
1948  * The main difference is that this method is not expected to throw exception.
1949  * This method has two outputs :
1950  *
1951  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1952  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1953  */
1954 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1955 {
1956   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1957   DataArrayInt *commonCells=0,*commonCellsI=0;
1958   int thisNbCells=getNumberOfCells();
1959   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1960   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1961   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1962   int otherNbCells=other->getNumberOfCells();
1963   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1964   arr2->alloc(otherNbCells,1);
1965   arr2->fillWithZero();
1966   int *arr2Ptr=arr2->getPointer();
1967   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1968   for(int i=0;i<nbOfCommon;i++)
1969     {
1970       int start=commonCellsPtr[commonCellsIPtr[i]];
1971       if(start<thisNbCells)
1972         {
1973           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1974             {
1975               int sig=commonCellsPtr[j]>0?1:-1;
1976               int val=std::abs(commonCellsPtr[j])-1;
1977               if(val>=thisNbCells)
1978                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1979             }
1980         }
1981     }
1982   arr2->setName(other->getName());
1983   if(arr2->presenceOfValue(0))
1984     return false;
1985   arr=arr2.retn();
1986   return true;
1987 }
1988
1989 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1990 {
1991   if(!other)
1992     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1993   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1994   if(!otherC)
1995     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1996   std::vector<const MEDCouplingUMesh *> ms(2);
1997   ms[0]=this;
1998   ms[1]=otherC;
1999   return MergeUMeshesOnSameCoords(ms);
2000 }
2001
2002 /*!
2003  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
2004  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
2005  * cellIds is not given explicitely but by a range python like.
2006  * 
2007  * \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.
2008  * \return a newly allocated
2009  * 
2010  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
2011  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
2012  */
2013 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
2014 {
2015   if(getMeshDimension()!=-1)
2016     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
2017   else
2018     {
2019       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
2020       if(newNbOfCells!=1)
2021         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2022       if(start!=0)
2023         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2024       incrRef();
2025       return const_cast<MEDCouplingUMesh *>(this);
2026     }
2027 }
2028
2029 /*!
2030  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
2031  * The result mesh shares or not the node coordinates array with \a this mesh depending
2032  * on \a keepCoords parameter.
2033  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
2034  *           to write this mesh to the MED file, its cells must be sorted using
2035  *           sortCellsInMEDFileFrmt().
2036  *  \param [in] begin - an array of cell ids to include to the new mesh.
2037  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
2038  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2039  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2040  *         by calling zipCoords().
2041  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2042  *         to delete this mesh using decrRef() as it is no more needed. 
2043  *  \throw If the coordinates array is not set.
2044  *  \throw If the nodal connectivity of cells is not defined.
2045  *  \throw If any cell id in the array \a begin is not valid.
2046  *
2047  *  \if ENABLE_EXAMPLES
2048  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
2049  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
2050  *  \endif
2051  */
2052 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
2053 {
2054   if(getMeshDimension()!=-1)
2055     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
2056   else
2057     {
2058       if(end-begin!=1)
2059         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2060       if(begin[0]!=0)
2061         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2062       incrRef();
2063       return const_cast<MEDCouplingUMesh *>(this);
2064     }
2065 }
2066
2067 /*!
2068  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2069  *
2070  * 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.
2071  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2072  * The number of cells of \b this will remain the same with this method.
2073  *
2074  * \param [in] begin begin of cell ids (included) of cells in this to assign
2075  * \param [in] end end of cell ids (excluded) of cells in this to assign
2076  * \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 ).
2077  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2078  */
2079 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2080 {
2081   checkConnectivityFullyDefined();
2082   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2083   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2084     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2085   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2086     {
2087       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2088       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2089       throw INTERP_KERNEL::Exception(oss.str().c_str());
2090     }
2091   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2092   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2093     {
2094       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2095       throw INTERP_KERNEL::Exception(oss.str().c_str());
2096     }
2097   int nbOfCells=getNumberOfCells();
2098   bool easyAssign=true;
2099   const int *connI=_nodal_connec_index->getConstPointer();
2100   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2101   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2102     {
2103       if(*it>=0 && *it<nbOfCells)
2104         {
2105           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2106         }
2107       else
2108         {
2109           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2110           throw INTERP_KERNEL::Exception(oss.str().c_str());
2111         }
2112     }
2113   if(easyAssign)
2114     {
2115       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2116       computeTypes();
2117     }
2118   else
2119     {
2120       DataArrayInt *arrOut=0,*arrIOut=0;
2121       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2122                                                arrOut,arrIOut);
2123       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2124       setConnectivity(arrOut,arrIOut,true);
2125     }
2126 }
2127
2128 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2129 {
2130   checkConnectivityFullyDefined();
2131   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2132   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2133     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2134   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2135     {
2136       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2137       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2138       throw INTERP_KERNEL::Exception(oss.str().c_str());
2139     }
2140   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2141   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2142     {
2143       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2144       throw INTERP_KERNEL::Exception(oss.str().c_str());
2145     }
2146   int nbOfCells=getNumberOfCells();
2147   bool easyAssign=true;
2148   const int *connI=_nodal_connec_index->getConstPointer();
2149   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2150   int it=start;
2151   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2152     {
2153       if(it>=0 && it<nbOfCells)
2154         {
2155           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2156         }
2157       else
2158         {
2159           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2160           throw INTERP_KERNEL::Exception(oss.str().c_str());
2161         }
2162     }
2163   if(easyAssign)
2164     {
2165       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2166       computeTypes();
2167     }
2168   else
2169     {
2170       DataArrayInt *arrOut=0,*arrIOut=0;
2171       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2172                                                 arrOut,arrIOut);
2173       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2174       setConnectivity(arrOut,arrIOut,true);
2175     }
2176 }                      
2177
2178 /*!
2179  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2180  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2181  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2182  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2183  *
2184  * \param [in] begin input start of array of node ids.
2185  * \param [in] end input end of array of node ids.
2186  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2187  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2188  */
2189 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2190 {
2191   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2192   checkConnectivityFullyDefined();
2193   int tmp=-1;
2194   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2195   std::vector<bool> fastFinder(sz,false);
2196   for(const int *work=begin;work!=end;work++)
2197     if(*work>=0 && *work<sz)
2198       fastFinder[*work]=true;
2199   int nbOfCells=getNumberOfCells();
2200   const int *conn=getNodalConnectivity()->getConstPointer();
2201   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2202   for(int i=0;i<nbOfCells;i++)
2203     {
2204       int ref=0,nbOfHit=0;
2205       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2206         if(*work2>=0)
2207           {
2208             ref++;
2209             if(fastFinder[*work2])
2210               nbOfHit++;
2211           }
2212       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2213         cellIdsKept->pushBackSilent(i);
2214     }
2215   cellIdsKeptArr=cellIdsKept.retn();
2216 }
2217
2218 /*!
2219  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2220  * this->getMeshDimension(), that bound some cells of \a this mesh.
2221  * The cells of lower dimension to include to the result mesh are selected basing on
2222  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2223  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2224  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2225  * created mesh shares the node coordinates array with \a this mesh. 
2226  *  \param [in] begin - the array of node ids.
2227  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2228  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2229  *         array \a begin are added, else cells whose any node is in the
2230  *         array \a begin are added.
2231  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2232  *         to delete this mesh using decrRef() as it is no more needed. 
2233  *  \throw If the coordinates array is not set.
2234  *  \throw If the nodal connectivity of cells is not defined.
2235  *  \throw If any node id in \a begin is not valid.
2236  *
2237  *  \if ENABLE_EXAMPLES
2238  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2239  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2240  *  \endif
2241  */
2242 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2243 {
2244   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2245   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2246   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2247   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2248   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2249 }
2250
2251 /*!
2252  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2253  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2254  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2255  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2256  *         by calling zipCoords().
2257  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2258  *         to delete this mesh using decrRef() as it is no more needed. 
2259  *  \throw If the coordinates array is not set.
2260  *  \throw If the nodal connectivity of cells is not defined.
2261  *
2262  *  \if ENABLE_EXAMPLES
2263  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2264  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2265  *  \endif
2266  */
2267 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2268 {
2269   DataArrayInt *desc=DataArrayInt::New();
2270   DataArrayInt *descIndx=DataArrayInt::New();
2271   DataArrayInt *revDesc=DataArrayInt::New();
2272   DataArrayInt *revDescIndx=DataArrayInt::New();
2273   //
2274   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2275   revDesc->decrRef();
2276   desc->decrRef();
2277   descIndx->decrRef();
2278   int nbOfCells=meshDM1->getNumberOfCells();
2279   const int *revDescIndxC=revDescIndx->getConstPointer();
2280   std::vector<int> boundaryCells;
2281   for(int i=0;i<nbOfCells;i++)
2282     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2283       boundaryCells.push_back(i);
2284   revDescIndx->decrRef();
2285   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2286   return ret;
2287 }
2288
2289 /*!
2290  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2291  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2292  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2293  */
2294 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2295 {
2296   checkFullyDefined();
2297   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2298   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2299   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2300   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2301   //
2302   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2303   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2304   //
2305   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2306   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2307   const int *revDescPtr=revDesc->getConstPointer();
2308   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2309   int nbOfCells=getNumberOfCells();
2310   std::vector<bool> ret1(nbOfCells,false);
2311   int sz=0;
2312   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2313     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2314       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2315   //
2316   DataArrayInt *ret2=DataArrayInt::New();
2317   ret2->alloc(sz,1);
2318   int *ret2Ptr=ret2->getPointer();
2319   sz=0;
2320   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2321     if(*it)
2322       *ret2Ptr++=sz;
2323   ret2->setName("BoundaryCells");
2324   return ret2;
2325 }
2326
2327 /*!
2328  * This method finds in \b this the cell ids that lie on mesh \b otherDimM1OnSameCoords.
2329  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2330  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2331  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2332  *
2333  * s0 is the cell ids set in \b this lying on at least one node in the fetched nodes in \b otherDimM1OnSameCoords.
2334  * This method returns the cells ids set s = s1 + s2 where:
2335  * 
2336  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2337  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2338  *
2339  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2340  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2341  *
2342  * \param [out] cellIdsRk0 a newly allocated array containing the cell ids of s0 (which are cell ids of \b this) in the above algorithm.
2343  * \param [out] cellIdsRk1 a newly allocated array containing the cell ids of s1+s2 \b into the \b cellIdsRk0 subset. To get the absolute ids of s1+s2, simply invoke
2344  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2345  */
2346 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2347 {
2348   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2349     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2350   checkConnectivityFullyDefined();
2351   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2352   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2353     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2354   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2355   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2356   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2357   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2358   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2359   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2360   DataArrayInt *idsOtherInConsti=0;
2361   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2362   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2363   if(!b)
2364     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2365   std::set<int> s1;
2366   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2367     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2368   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2369   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2370   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2371   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2372   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2373   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2374   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2375   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2376   neighThisPartAuto=0;
2377   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2378   const int li[2]={0,1};
2379   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2380   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2381   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2382   s_renum1->sort();
2383   //
2384   cellIdsRk0=s0arr.retn();
2385   cellIdsRk1=s_renum1.retn();
2386 }
2387
2388 /*!
2389  * 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
2390  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2391  * 
2392  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2393  */
2394 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2395 {
2396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2397   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2398   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2399   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2400   //
2401   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2402   revDesc=0; desc=0; descIndx=0;
2403   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2405   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2406 }
2407
2408 /*!
2409  * Finds nodes lying on the boundary of \a this mesh.
2410  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2411  *          nodes. The caller is to delete this array using decrRef() as it is no
2412  *          more needed.
2413  *  \throw If the coordinates array is not set.
2414  *  \throw If the nodal connectivity of cells is node defined.
2415  *
2416  *  \if ENABLE_EXAMPLES
2417  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2418  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2419  *  \endif
2420  */
2421 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2422 {
2423   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2424   return skin->computeFetchedNodeIds();
2425 }
2426
2427 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2428 {
2429   incrRef();
2430   return const_cast<MEDCouplingUMesh *>(this);
2431 }
2432
2433 /*!
2434  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2435  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2436  * 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.
2437  * 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.
2438  * 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.
2439  *
2440  * \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
2441  *             parameter is altered during the call.
2442  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2443  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2444  * \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.
2445  *
2446  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2447  */
2448 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2449                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const
2450 {
2451   checkFullyDefined();
2452   otherDimM1OnSameCoords.checkFullyDefined();
2453   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2454     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2455   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2456     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2457   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2458   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2459   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2461   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2462   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2463   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2464   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2465   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2466   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2467   //
2468   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2469   int nCells2 = m0Part2->getNumberOfCells();
2470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2471   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2472   // Neighbor information of the mesh without considering the crack (serves to count how many connex pieces it is made of)
2473   DataArrayInt *tmp00=0,*tmp11=0;
2474   MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00, tmp00, tmp11);
2475   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighInit00(tmp00);
2476   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighIInit00(tmp11);
2477   // Neighbor information of the mesh WITH the crack (some neighbors are removed):
2478   DataArrayInt *idsTmp=0;
2479   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2480   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2481   if(!b)
2482     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2483   // In the neighbor information remove the connection between high dimension cells and its low level constituents which are part
2484   // of the frontier given in parameter (i.e. the cells of low dimension from the group delimiting the crack):
2485   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2486   DataArrayInt *tmp0=0,*tmp1=0;
2487   // Compute the neighbor of each cell in m0Part2, taking into account the broken link above. Two
2488   // cells on either side of the crack (defined by the mesh of low dimension) are not neighbor anymore.
2489   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2490   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2491   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2492
2493   // For each initial connex part of the sub-mesh (or said differently for each independent crack):
2494   int seed = 0, nIter = 0;
2495   int nIterMax = nCells2+1; // Safety net for the loop
2496   std::vector<bool> hitCells(nCells2);
2497   hitCells.assign(nCells2, false);
2498   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum = DataArrayInt::New();
2499   cellsToModifyConn0_torenum->alloc(0,1);
2500   while (nIter < nIterMax)
2501     {
2502       if (std::find(hitCells.begin(), hitCells.end(), false) == hitCells.end())
2503         break;
2504       // Connex zone without the crack (to compute the next seed really)
2505       int dnu;
2506       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connexCheck = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neighInit00,neighIInit00, -1, dnu);
2507       int cnt = 0;
2508       for (int * ptr = connexCheck->getPointer(); cnt < connexCheck->getNumberOfTuples(); ptr++, cnt++)
2509         hitCells[*ptr] = true;
2510       // Connex zone WITH the crack (to identify cells lying on either part of the crack)
2511       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> spreadZone = MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(&seed, &seed+1, neigh00,neighI00, -1, dnu);
2512       cellsToModifyConn0_torenum = DataArrayInt::Aggregate(cellsToModifyConn0_torenum, spreadZone, 0);
2513       // Compute next seed, i.e. a cell in another connex part:
2514       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comple = cellsToModifyConn0_torenum->buildComplement(nCells2);
2515       seed = comple->getIJ(0,0);
2516       nIter++;
2517     }
2518   if (nIter >= nIterMax)
2519     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate(): internal error - too many iterations.");
2520
2521   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2522   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2523   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2524   //
2525   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2526   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2527   nodeIdsToDuplicate=s3.retn();
2528 }
2529
2530 /*!
2531  * This method operates a modification of the connectivity and coords in \b this.
2532  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2533  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2534  * 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
2535  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2536  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2537  * 
2538  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2539  * 
2540  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2541  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2542  */
2543 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2544 {
2545   int nbOfNodes=getNumberOfNodes();
2546   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2547   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2548 }
2549
2550 /*!
2551  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2552  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2553  *
2554  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2555  *
2556  * \sa renumberNodesInConn
2557  */
2558 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2559 {
2560   checkConnectivityFullyDefined();
2561   int *conn(getNodalConnectivity()->getPointer());
2562   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2563   int nbOfCells(getNumberOfCells());
2564   for(int i=0;i<nbOfCells;i++)
2565     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2566       {
2567         int& node=conn[iconn];
2568         if(node>=0)//avoid polyhedron separator
2569           {
2570             node+=offset;
2571           }
2572       }
2573   _nodal_connec->declareAsNew();
2574   updateTime();
2575 }
2576
2577 /*!
2578  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2579  *  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
2580  *  of a big mesh.
2581  */
2582 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2583 {
2584   checkConnectivityFullyDefined();
2585   int *conn(getNodalConnectivity()->getPointer());
2586   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2587   int nbOfCells(getNumberOfCells());
2588   for(int i=0;i<nbOfCells;i++)
2589     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2590       {
2591         int& node=conn[iconn];
2592         if(node>=0)//avoid polyhedron separator
2593           {
2594             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2595             if(it!=newNodeNumbersO2N.end())
2596               {
2597                 node=(*it).second;
2598               }
2599             else
2600               {
2601                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2602                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2603               }
2604           }
2605       }
2606   _nodal_connec->declareAsNew();
2607   updateTime();
2608 }
2609
2610 /*!
2611  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2612  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2613  * This method is a generalization of shiftNodeNumbersInConn().
2614  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2615  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2616  *         this->getNumberOfNodes(), in "Old to New" mode. 
2617  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2618  *  \throw If the nodal connectivity of cells is not defined.
2619  *
2620  *  \if ENABLE_EXAMPLES
2621  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2622  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2623  *  \endif
2624  */
2625 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2626 {
2627   checkConnectivityFullyDefined();
2628   int *conn=getNodalConnectivity()->getPointer();
2629   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2630   int nbOfCells(getNumberOfCells());
2631   for(int i=0;i<nbOfCells;i++)
2632     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2633       {
2634         int& node=conn[iconn];
2635         if(node>=0)//avoid polyhedron separator
2636           {
2637             node=newNodeNumbersO2N[node];
2638           }
2639       }
2640   _nodal_connec->declareAsNew();
2641   updateTime();
2642 }
2643
2644 /*!
2645  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2646  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2647  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2648  * 
2649  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2650  */
2651 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2652 {
2653   checkConnectivityFullyDefined();
2654   int *conn=getNodalConnectivity()->getPointer();
2655   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2656   int nbOfCells=getNumberOfCells();
2657   for(int i=0;i<nbOfCells;i++)
2658     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2659       {
2660         int& node=conn[iconn];
2661         if(node>=0)//avoid polyhedron separator
2662           {
2663             node+=delta;
2664           }
2665       }
2666   _nodal_connec->declareAsNew();
2667   updateTime();
2668 }
2669
2670 /*!
2671  * This method operates a modification of the connectivity in \b this.
2672  * 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.
2673  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2674  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2675  * 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
2676  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2677  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2678  * 
2679  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2680  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2681  * 
2682  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2683  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2684  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2685  */
2686 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2687 {
2688   checkConnectivityFullyDefined();
2689   std::map<int,int> m;
2690   int val=offset;
2691   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2692     m[*work]=val;
2693   int *conn=getNodalConnectivity()->getPointer();
2694   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2695   int nbOfCells=getNumberOfCells();
2696   for(int i=0;i<nbOfCells;i++)
2697     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2698       {
2699         int& node=conn[iconn];
2700         if(node>=0)//avoid polyhedron separator
2701           {
2702             std::map<int,int>::iterator it=m.find(node);
2703             if(it!=m.end())
2704               node=(*it).second;
2705           }
2706       }
2707   updateTime();
2708 }
2709
2710 /*!
2711  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2712  *
2713  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2714  * After the call of this method the number of cells remains the same as before.
2715  *
2716  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2717  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2718  * be strictly in [0;this->getNumberOfCells()).
2719  *
2720  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2721  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2722  * should be contained in[0;this->getNumberOfCells()).
2723  * 
2724  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2725  */
2726 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2727 {
2728   checkConnectivityFullyDefined();
2729   int nbCells=getNumberOfCells();
2730   const int *array=old2NewBg;
2731   if(check)
2732     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2733   //
2734   const int *conn=_nodal_connec->getConstPointer();
2735   const int *connI=_nodal_connec_index->getConstPointer();
2736   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2737   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2738   const int *n2oPtr=n2o->begin();
2739   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2740   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2741   newConn->copyStringInfoFrom(*_nodal_connec);
2742   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2743   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2744   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2745   //
2746   int *newC=newConn->getPointer();
2747   int *newCI=newConnI->getPointer();
2748   int loc=0;
2749   newCI[0]=loc;
2750   for(int i=0;i<nbCells;i++)
2751     {
2752       int pos=n2oPtr[i];
2753       int nbOfElts=connI[pos+1]-connI[pos];
2754       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2755       loc+=nbOfElts;
2756       newCI[i+1]=loc;
2757     }
2758   //
2759   setConnectivity(newConn,newConnI);
2760   if(check)
2761     free(const_cast<int *>(array));
2762 }
2763
2764 /*!
2765  * Finds cells whose bounding boxes intersect a given bounding box.
2766  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2767  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2768  *         zMax (if in 3D). 
2769  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2770  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2771  *         extent of the bounding box of cell to produce an addition to this bounding box.
2772  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2773  *         cells. The caller is to delete this array using decrRef() as it is no more
2774  *         needed. 
2775  *  \throw If the coordinates array is not set.
2776  *  \throw If the nodal connectivity of cells is not defined.
2777  *
2778  *  \if ENABLE_EXAMPLES
2779  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2780  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2781  *  \endif
2782  */
2783 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2784 {
2785   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2786   if(getMeshDimension()==-1)
2787     {
2788       elems->pushBackSilent(0);
2789       return elems.retn();
2790     }
2791   int dim=getSpaceDimension();
2792   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2793   const int* conn      = getNodalConnectivity()->getConstPointer();
2794   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2795   const double* coords = getCoords()->getConstPointer();
2796   int nbOfCells=getNumberOfCells();
2797   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2798     {
2799       for (int i=0; i<dim; i++)
2800         {
2801           elem_bb[i*2]=std::numeric_limits<double>::max();
2802           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2803         }
2804
2805       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2806         {
2807           int node= conn[inode];
2808           if(node>=0)//avoid polyhedron separator
2809             {
2810               for (int idim=0; idim<dim; idim++)
2811                 {
2812                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2813                     {
2814                       elem_bb[idim*2] = coords[node*dim+idim] ;
2815                     }
2816                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2817                     {
2818                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2819                     }
2820                 }
2821             }
2822         }
2823       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2824         elems->pushBackSilent(ielem);
2825     }
2826   return elems.retn();
2827 }
2828
2829 /*!
2830  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2831  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2832  * added in 'elems' parameter.
2833  */
2834 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2835 {
2836   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2837   if(getMeshDimension()==-1)
2838     {
2839       elems->pushBackSilent(0);
2840       return elems.retn();
2841     }
2842   int dim=getSpaceDimension();
2843   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2844   const int* conn      = getNodalConnectivity()->getConstPointer();
2845   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2846   const double* coords = getCoords()->getConstPointer();
2847   int nbOfCells=getNumberOfCells();
2848   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2849     {
2850       for (int i=0; i<dim; i++)
2851         {
2852           elem_bb[i*2]=std::numeric_limits<double>::max();
2853           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2854         }
2855
2856       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2857         {
2858           int node= conn[inode];
2859           if(node>=0)//avoid polyhedron separator
2860             {
2861               for (int idim=0; idim<dim; idim++)
2862                 {
2863                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2864                     {
2865                       elem_bb[idim*2] = coords[node*dim+idim] ;
2866                     }
2867                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2868                     {
2869                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2870                     }
2871                 }
2872             }
2873         }
2874       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2875         elems->pushBackSilent(ielem);
2876     }
2877   return elems.retn();
2878 }
2879
2880 /*!
2881  * Returns a type of a cell by its id.
2882  *  \param [in] cellId - the id of the cell of interest.
2883  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2884  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2885  */
2886 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2887 {
2888   const int *ptI=_nodal_connec_index->getConstPointer();
2889   const int *pt=_nodal_connec->getConstPointer();
2890   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2891     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2892   else
2893     {
2894       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2895       throw INTERP_KERNEL::Exception(oss.str().c_str());
2896     }
2897 }
2898
2899 /*!
2900  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2901  * This method does not throw exception if geometric type \a type is not in \a this.
2902  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2903  * The coordinates array is not considered here.
2904  *
2905  * \param [in] type the geometric type
2906  * \return cell ids in this having geometric type \a type.
2907  */
2908 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2909 {
2910
2911   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2912   ret->alloc(0,1);
2913   checkConnectivityFullyDefined();
2914   int nbCells=getNumberOfCells();
2915   int mdim=getMeshDimension();
2916   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2917   if(mdim!=(int)cm.getDimension())
2918     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2919   const int *ptI=_nodal_connec_index->getConstPointer();
2920   const int *pt=_nodal_connec->getConstPointer();
2921   for(int i=0;i<nbCells;i++)
2922     {
2923       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2924         ret->pushBackSilent(i);
2925     }
2926   return ret.retn();
2927 }
2928
2929 /*!
2930  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2931  */
2932 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2933 {
2934   const int *ptI=_nodal_connec_index->getConstPointer();
2935   const int *pt=_nodal_connec->getConstPointer();
2936   int nbOfCells=getNumberOfCells();
2937   int ret=0;
2938   for(int i=0;i<nbOfCells;i++)
2939     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2940       ret++;
2941   return ret;
2942 }
2943
2944 /*!
2945  * Returns the nodal connectivity of a given cell.
2946  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2947  * all returned node ids can be used in getCoordinatesOfNode().
2948  *  \param [in] cellId - an id of the cell of interest.
2949  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2950  *         cleared before the appending.
2951  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2952  */
2953 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2954 {
2955   const int *ptI=_nodal_connec_index->getConstPointer();
2956   const int *pt=_nodal_connec->getConstPointer();
2957   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2958     if(*w>=0)
2959       conn.push_back(*w);
2960 }
2961
2962 std::string MEDCouplingUMesh::simpleRepr() const
2963 {
2964   static const char msg0[]="No coordinates specified !";
2965   std::ostringstream ret;
2966   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2967   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2968   int tmpp1,tmpp2;
2969   double tt=getTime(tmpp1,tmpp2);
2970   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2971   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2972   if(_mesh_dim>=-1)
2973     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2974   else
2975     { ret << " Mesh dimension has not been set or is invalid !"; }
2976   if(_coords!=0)
2977     {
2978       const int spaceDim=getSpaceDimension();
2979       ret << spaceDim << "\nInfo attached on space dimension : ";
2980       for(int i=0;i<spaceDim;i++)
2981         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2982       ret << "\n";
2983     }
2984   else
2985     ret << msg0 << "\n";
2986   ret << "Number of nodes : ";
2987   if(_coords!=0)
2988     ret << getNumberOfNodes() << "\n";
2989   else
2990     ret << msg0 << "\n";
2991   ret << "Number of cells : ";
2992   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2993     ret << getNumberOfCells() << "\n";
2994   else
2995     ret << "No connectivity specified !" << "\n";
2996   ret << "Cell types present : ";
2997   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2998     {
2999       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
3000       ret << cm.getRepr() << " ";
3001     }
3002   ret << "\n";
3003   return ret.str();
3004 }
3005
3006 std::string MEDCouplingUMesh::advancedRepr() const
3007 {
3008   std::ostringstream ret;
3009   ret << simpleRepr();
3010   ret << "\nCoordinates array : \n___________________\n\n";
3011   if(_coords)
3012     _coords->reprWithoutNameStream(ret);
3013   else
3014     ret << "No array set !\n";
3015   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
3016   reprConnectivityOfThisLL(ret);
3017   return ret.str();
3018 }
3019
3020 /*!
3021  * This method returns a C++ code that is a dump of \a this.
3022  * This method will throw if this is not fully defined.
3023  */
3024 std::string MEDCouplingUMesh::cppRepr() const
3025 {
3026   static const char coordsName[]="coords";
3027   static const char connName[]="conn";
3028   static const char connIName[]="connI";
3029   checkFullyDefined();
3030   std::ostringstream ret; ret << "// coordinates" << std::endl;
3031   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
3032   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
3033   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
3034   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
3035   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
3036   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
3037   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
3038   return ret.str();
3039 }
3040
3041 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3042 {
3043   std::ostringstream ret;
3044   reprConnectivityOfThisLL(ret);
3045   return ret.str();
3046 }
3047
3048 /*!
3049  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3050  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3051  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3052  * some algos).
3053  * 
3054  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3055  * 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
3056  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3057  */
3058 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3059 {
3060   int mdim=getMeshDimension();
3061   if(mdim<0)
3062     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3063   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3064   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3065   bool needToCpyCT=true;
3066   if(!_nodal_connec)
3067     {
3068       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3069       needToCpyCT=false;
3070     }
3071   else
3072     {
3073       tmp1=_nodal_connec;
3074       tmp1->incrRef();
3075     }
3076   if(!_nodal_connec_index)
3077     {
3078       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3079       needToCpyCT=false;
3080     }
3081   else
3082     {
3083       tmp2=_nodal_connec_index;
3084       tmp2->incrRef();
3085     }
3086   ret->setConnectivity(tmp1,tmp2,false);
3087   if(needToCpyCT)
3088     ret->_types=_types;
3089   if(!_coords)
3090     {
3091       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3092       ret->setCoords(coords);
3093     }
3094   else
3095     ret->setCoords(_coords);
3096   return ret.retn();
3097 }
3098
3099 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3100 {
3101   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3102     {
3103       int nbOfCells=getNumberOfCells();
3104       const int *c=_nodal_connec->getConstPointer();
3105       const int *ci=_nodal_connec_index->getConstPointer();
3106       for(int i=0;i<nbOfCells;i++)
3107         {
3108           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3109           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3110           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3111           stream << "\n";
3112         }
3113     }
3114   else
3115     stream << "Connectivity not defined !\n";
3116 }
3117
3118 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3119 {
3120   const int *ptI=_nodal_connec_index->getConstPointer();
3121   const int *pt=_nodal_connec->getConstPointer();
3122   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3123     return ptI[cellId+1]-ptI[cellId]-1;
3124   else
3125     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3126 }
3127
3128 /*!
3129  * Returns types of cells of the specified part of \a this mesh.
3130  * This method avoids computing sub-mesh explicitely to get its types.
3131  *  \param [in] begin - an array of cell ids of interest.
3132  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3133  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3134  *         describing the cell types. 
3135  *  \throw If the coordinates array is not set.
3136  *  \throw If the nodal connectivity of cells is not defined.
3137  *  \sa getAllGeoTypes()
3138  */
3139 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3140 {
3141   checkFullyDefined();
3142   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3143   const int *conn=_nodal_connec->getConstPointer();
3144   const int *connIndex=_nodal_connec_index->getConstPointer();
3145   for(const int *w=begin;w!=end;w++)
3146     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3147   return ret;
3148 }
3149
3150 /*!
3151  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3152  * a set of types of cells constituting \a this mesh. 
3153  * This method is for advanced users having prepared their connectivity before. For
3154  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3155  *  \param [in] conn - the nodal connectivity array. 
3156  *  \param [in] connIndex - the nodal connectivity index array.
3157  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3158  *         mesh is updated.
3159  */
3160 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3161 {
3162   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3163   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3164   if(isComputingTypes)
3165     computeTypes();
3166   declareAsNew();
3167 }
3168
3169 /*!
3170  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3171  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3172  */
3173 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3174     _nodal_connec(0),_nodal_connec_index(0),
3175     _types(other._types)
3176 {
3177   if(other._nodal_connec)
3178     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3179   if(other._nodal_connec_index)
3180     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3181 }
3182
3183 MEDCouplingUMesh::~MEDCouplingUMesh()
3184 {
3185   if(_nodal_connec)
3186     _nodal_connec->decrRef();
3187   if(_nodal_connec_index)
3188     _nodal_connec_index->decrRef();
3189 }
3190
3191 /*!
3192  * Recomputes a set of cell types of \a this mesh. For more info see
3193  * \ref MEDCouplingUMeshNodalConnectivity.
3194  */
3195 void MEDCouplingUMesh::computeTypes()
3196 {
3197   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3198 }
3199
3200 /*!
3201  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3202  */
3203 void MEDCouplingUMesh::checkFullyDefined() const
3204 {
3205   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3206     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3207 }
3208
3209 /*!
3210  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3211  */
3212 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3213 {
3214   if(!_nodal_connec_index || !_nodal_connec)
3215     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3216 }
3217
3218 /*!
3219  * Returns a number of cells constituting \a this mesh. 
3220  *  \return int - the number of cells in \a this mesh.
3221  *  \throw If the nodal connectivity of cells is not defined.
3222  */
3223 int MEDCouplingUMesh::getNumberOfCells() const
3224
3225   if(_nodal_connec_index)
3226     return _nodal_connec_index->getNumberOfTuples()-1;
3227   else
3228     if(_mesh_dim==-1)
3229       return 1;
3230     else
3231       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3232 }
3233
3234 /*!
3235  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3236  * mesh. For more info see \ref MEDCouplingMeshesPage.
3237  *  \return int - the dimension of \a this mesh.
3238  *  \throw If the mesh dimension is not defined using setMeshDimension().
3239  */
3240 int MEDCouplingUMesh::getMeshDimension() const
3241 {
3242   if(_mesh_dim<-1)
3243     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3244   return _mesh_dim;
3245 }
3246
3247 /*!
3248  * Returns a length of the nodal connectivity array.
3249  * This method is for test reason. Normally the integer returned is not useable by
3250  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3251  *  \return int - the length of the nodal connectivity array.
3252  */
3253 int MEDCouplingUMesh::getMeshLength() const
3254 {
3255   return _nodal_connec->getNbOfElems();
3256 }
3257
3258 /*!
3259  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3260  */
3261 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3262 {
3263   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3264   tinyInfo.push_back(getMeshDimension());
3265   tinyInfo.push_back(getNumberOfCells());
3266   if(_nodal_connec)
3267     tinyInfo.push_back(getMeshLength());
3268   else
3269     tinyInfo.push_back(-1);
3270 }
3271
3272 /*!
3273  * First step of unserialization process.
3274  */
3275 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3276 {
3277   return tinyInfo[6]<=0;
3278 }
3279
3280 /*!
3281  * Second step of serialization process.
3282  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3283  */
3284 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3285 {
3286   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3287   if(tinyInfo[5]!=-1)
3288     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3289 }
3290
3291 /*!
3292  * Third and final step of serialization process.
3293  */
3294 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3295 {
3296   MEDCouplingPointSet::serialize(a1,a2);
3297   if(getMeshDimension()>-1)
3298     {
3299       a1=DataArrayInt::New();
3300       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3301       int *ptA1=a1->getPointer();
3302       const int *conn=getNodalConnectivity()->getConstPointer();
3303       const int *index=getNodalConnectivityIndex()->getConstPointer();
3304       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3305       std::copy(conn,conn+getMeshLength(),ptA1);
3306     }
3307   else
3308     a1=0;
3309 }
3310
3311 /*!
3312  * Second and final unserialization process.
3313  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3314  */
3315 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3316 {
3317   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3318   setMeshDimension(tinyInfo[5]);
3319   if(tinyInfo[7]!=-1)
3320     {
3321       // Connectivity
3322       const int *recvBuffer=a1->getConstPointer();
3323       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3324       myConnecIndex->alloc(tinyInfo[6]+1,1);
3325       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3326       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3327       myConnec->alloc(tinyInfo[7],1);
3328       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3329       setConnectivity(myConnec, myConnecIndex);
3330     }
3331 }
3332
3333 /*!
3334  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3335  * CellIds are given using range specified by a start an end and step.
3336  */
3337 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3338 {
3339   checkFullyDefined();
3340   int ncell=getNumberOfCells();
3341   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3342   ret->_mesh_dim=_mesh_dim;
3343   ret->setCoords(_coords);
3344   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3345   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3346   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3347   int work=start;
3348   const int *conn=_nodal_connec->getConstPointer();
3349   const int *connIndex=_nodal_connec_index->getConstPointer();
3350   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3351     {
3352       if(work>=0 && work<ncell)
3353         {
3354           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3355         }
3356       else
3357         {
3358           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3359           throw INTERP_KERNEL::Exception(oss.str().c_str());
3360         }
3361     }
3362   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3363   int *newConnPtr=newConn->getPointer();
3364   std::set<INTERP_KERNEL::NormalizedCellType> types;
3365   work=start;
3366   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3367     {
3368       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3369       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3370     }
3371   ret->setConnectivity(newConn,newConnI,false);
3372   ret->_types=types;
3373   ret->copyTinyInfoFrom(this);
3374   return ret.retn();
3375 }
3376
3377 /*!
3378  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3379  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3380  * The return newly allocated mesh will share the same coordinates as \a this.
3381  */
3382 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3383 {
3384   checkConnectivityFullyDefined();
3385   int ncell=getNumberOfCells();
3386   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3387   ret->_mesh_dim=_mesh_dim;
3388   ret->setCoords(_coords);
3389   std::size_t nbOfElemsRet=std::distance(begin,end);
3390   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3391   connIndexRet[0]=0;
3392   const int *conn=_nodal_connec->getConstPointer();
3393   const int *connIndex=_nodal_connec_index->getConstPointer();
3394   int newNbring=0;
3395   for(const int *work=begin;work!=end;work++,newNbring++)
3396     {
3397       if(*work>=0 && *work<ncell)
3398         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3399       else
3400         {
3401           free(connIndexRet);
3402           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3403           throw INTERP_KERNEL::Exception(oss.str().c_str());
3404         }
3405     }
3406   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3407   int *connRetWork=connRet;
3408   std::set<INTERP_KERNEL::NormalizedCellType> types;
3409   for(const int *work=begin;work!=end;work++)
3410     {
3411       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3412       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3413     }
3414   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3415   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3416   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3417   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3418   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3419   ret->_types=types;
3420   ret->copyTinyInfoFrom(this);
3421   return ret.retn();
3422 }
3423
3424 /*!
3425  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3426  * mesh.<br>
3427  * For 1D cells, the returned field contains lengths.<br>
3428  * For 2D cells, the returned field contains areas.<br>
3429  * For 3D cells, the returned field contains volumes.
3430  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3431  *         orientation, i.e. the volume is always positive.
3432  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3433  *         and one time . The caller is to delete this field using decrRef() as it is no
3434  *         more needed.
3435  */
3436 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3437 {
3438   std::string name="MeasureOfMesh_";
3439   name+=getName();
3440   int nbelem=getNumberOfCells();
3441   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3442   field->setName(name);
3443   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3444   array->alloc(nbelem,1);
3445   double *area_vol=array->getPointer();
3446   field->setArray(array) ; array=0;
3447   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3448   field->synchronizeTimeWithMesh();
3449   if(getMeshDimension()!=-1)
3450     {
3451       int ipt;
3452       INTERP_KERNEL::NormalizedCellType type;
3453       int dim_space=getSpaceDimension();
3454       const double *coords=getCoords()->getConstPointer();
3455       const int *connec=getNodalConnectivity()->getConstPointer();
3456       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3457       for(int iel=0;iel<nbelem;iel++)
3458         {
3459           ipt=connec_index[iel];
3460           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3461           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);
3462         }
3463       if(isAbs)
3464         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3465     }
3466   else
3467     {
3468       area_vol[0]=std::numeric_limits<double>::max();
3469     }
3470   return field.retn();
3471 }
3472
3473 /*!
3474  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3475  * mesh.<br>
3476  * For 1D cells, the returned array contains lengths.<br>
3477  * For 2D cells, the returned array contains areas.<br>
3478  * For 3D cells, the returned array contains volumes.
3479  * This method avoids building explicitly a part of \a this mesh to perform the work.
3480  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3481  *         orientation, i.e. the volume is always positive.
3482  *  \param [in] begin - an array of cell ids of interest.
3483  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3484  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3485  *          delete this array using decrRef() as it is no more needed.
3486  * 
3487  *  \if ENABLE_EXAMPLES
3488  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3489  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3490  *  \endif
3491  *  \sa getMeasureField()
3492  */
3493 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3494 {
3495   std::string name="PartMeasureOfMesh_";
3496   name+=getName();
3497   int nbelem=(int)std::distance(begin,end);
3498   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3499   array->setName(name);
3500   array->alloc(nbelem,1);
3501   double *area_vol=array->getPointer();
3502   if(getMeshDimension()!=-1)
3503     {
3504       int ipt;
3505       INTERP_KERNEL::NormalizedCellType type;
3506       int dim_space=getSpaceDimension();
3507       const double *coords=getCoords()->getConstPointer();
3508       const int *connec=getNodalConnectivity()->getConstPointer();
3509       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3510       for(const int *iel=begin;iel!=end;iel++)
3511         {
3512           ipt=connec_index[*iel];
3513           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3514           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3515         }
3516       if(isAbs)
3517         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3518     }
3519   else
3520     {
3521       area_vol[0]=std::numeric_limits<double>::max();
3522     }
3523   return array.retn();
3524 }
3525
3526 /*!
3527  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3528  * \a this one. The returned field contains the dual cell volume for each corresponding
3529  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3530  *  the dual mesh in P1 sens of \a this.<br>
3531  * For 1D cells, the returned field contains lengths.<br>
3532  * For 2D cells, the returned field contains areas.<br>
3533  * For 3D cells, the returned field contains volumes.
3534  * This method is useful to check "P1*" conservative interpolators.
3535  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3536  *         orientation, i.e. the volume is always positive.
3537  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3538  *          nodes and one time. The caller is to delete this array using decrRef() as
3539  *          it is no more needed.
3540  */
3541 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3542 {
3543   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3544   std::string name="MeasureOnNodeOfMesh_";
3545   name+=getName();
3546   int nbNodes=getNumberOfNodes();
3547   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3548   double cst=1./((double)getMeshDimension()+1.);
3549   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3550   array->alloc(nbNodes,1);
3551   double *valsToFill=array->getPointer();
3552   std::fill(valsToFill,valsToFill+nbNodes,0.);
3553   const double *values=tmp->getArray()->getConstPointer();
3554   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3555   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3556   getReverseNodalConnectivity(da,daInd);
3557   const int *daPtr=da->getConstPointer();
3558   const int *daIPtr=daInd->getConstPointer();
3559   for(int i=0;i<nbNodes;i++)
3560     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3561       valsToFill[i]+=cst*values[*cell];
3562   ret->setMesh(this);
3563   ret->setArray(array);
3564   return ret.retn();
3565 }
3566
3567 /*!
3568  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3569  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3570  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3571  * and are normalized.
3572  * <br> \a this can be either 
3573  * - a  2D mesh in 2D or 3D space or 
3574  * - an 1D mesh in 2D space.
3575  * 
3576  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3577  *          cells and one time. The caller is to delete this field using decrRef() as
3578  *          it is no more needed.
3579  *  \throw If the nodal connectivity of cells is not defined.
3580  *  \throw If the coordinates array is not set.
3581  *  \throw If the mesh dimension is not set.
3582  *  \throw If the mesh and space dimension is not as specified above.
3583  */
3584 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3585 {
3586   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3587     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3588   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3589   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3590   int nbOfCells=getNumberOfCells();
3591   int nbComp=getMeshDimension()+1;
3592   array->alloc(nbOfCells,nbComp);
3593   double *vals=array->getPointer();
3594   const int *connI=_nodal_connec_index->getConstPointer();
3595   const int *conn=_nodal_connec->getConstPointer();
3596   const double *coords=_coords->getConstPointer();
3597   if(getMeshDimension()==2)
3598     {
3599       if(getSpaceDimension()==3)
3600         {
3601           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3602           const double *locPtr=loc->getConstPointer();
3603           for(int i=0;i<nbOfCells;i++,vals+=3)
3604             {
3605               int offset=connI[i];
3606               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3607               double n=INTERP_KERNEL::norm<3>(vals);
3608               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3609             }
3610         }
3611       else
3612         {
3613           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3614           const double *isAbsPtr=isAbs->getArray()->begin();
3615           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3616             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3617         }
3618     }
3619   else//meshdimension==1
3620     {
3621       double tmp[2];
3622       for(int i=0;i<nbOfCells;i++)
3623         {
3624           int offset=connI[i];
3625           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3626           double n=INTERP_KERNEL::norm<2>(tmp);
3627           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3628           *vals++=-tmp[1];
3629           *vals++=tmp[0];
3630         }
3631     }
3632   ret->setArray(array);
3633   ret->setMesh(this);
3634   ret->synchronizeTimeWithSupport();
3635   return ret.retn();
3636 }
3637
3638 /*!
3639  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3640  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3641  * and are normalized.
3642  * <br> \a this can be either 
3643  * - a  2D mesh in 2D or 3D space or 
3644  * - an 1D mesh in 2D space.
3645  * 
3646  * This method avoids building explicitly a part of \a this mesh to perform the work.
3647  *  \param [in] begin - an array of cell ids of interest.
3648  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3649  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3650  *          cells and one time. The caller is to delete this field using decrRef() as
3651  *          it is no more needed.
3652  *  \throw If the nodal connectivity of cells is not defined.
3653  *  \throw If the coordinates array is not set.
3654  *  \throw If the mesh dimension is not set.
3655  *  \throw If the mesh and space dimension is not as specified above.
3656  *  \sa buildOrthogonalField()
3657  *
3658  *  \if ENABLE_EXAMPLES
3659  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3660  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3661  *  \endif
3662  */
3663 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3664 {
3665   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3666     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3667   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3668   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3669   std::size_t nbelems=std::distance(begin,end);
3670   int nbComp=getMeshDimension()+1;
3671   array->alloc((int)nbelems,nbComp);
3672   double *vals=array->getPointer();
3673   const int *connI=_nodal_connec_index->getConstPointer();
3674   const int *conn=_nodal_connec->getConstPointer();
3675   const double *coords=_coords->getConstPointer();
3676   if(getMeshDimension()==2)
3677     {
3678       if(getSpaceDimension()==3)
3679         {
3680           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3681           const double *locPtr=loc->getConstPointer();
3682           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3683             {
3684               int offset=connI[*i];
3685               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3686               double n=INTERP_KERNEL::norm<3>(vals);
3687               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3688             }
3689         }
3690       else
3691         {
3692           for(std::size_t i=0;i<nbelems;i++)
3693             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3694         }
3695     }
3696   else//meshdimension==1
3697     {
3698       double tmp[2];
3699       for(const int *i=begin;i!=end;i++)
3700         {
3701           int offset=connI[*i];
3702           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3703           double n=INTERP_KERNEL::norm<2>(tmp);
3704           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3705           *vals++=-tmp[1];
3706           *vals++=tmp[0];
3707         }
3708     }
3709   ret->setArray(array);
3710   ret->setMesh(this);
3711   ret->synchronizeTimeWithSupport();
3712   return ret.retn();
3713 }
3714
3715 /*!
3716  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3717  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3718  * and are \b not normalized.
3719  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3720  *          cells and one time. The caller is to delete this field using decrRef() as
3721  *          it is no more needed.
3722  *  \throw If the nodal connectivity of cells is not defined.
3723  *  \throw If the coordinates array is not set.
3724  *  \throw If \a this->getMeshDimension() != 1.
3725  *  \throw If \a this mesh includes cells of type other than SEG2.
3726  */
3727 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3728 {
3729   if(getMeshDimension()!=1)
3730     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3731   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3732     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3733   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3734   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3735   int nbOfCells=getNumberOfCells();
3736   int spaceDim=getSpaceDimension();
3737   array->alloc(nbOfCells,spaceDim);
3738   double *pt=array->getPointer();
3739   const double *coo=getCoords()->getConstPointer();
3740   std::vector<int> conn;
3741   conn.reserve(2);
3742   for(int i=0;i<nbOfCells;i++)
3743     {
3744       conn.resize(0);
3745       getNodeIdsOfCell(i,conn);
3746       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3747     }
3748   ret->setArray(array);
3749   ret->setMesh(this);
3750   ret->synchronizeTimeWithSupport();
3751   return ret.retn();
3752 }
3753
3754 /*!
3755  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3756  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3757  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3758  * from. If a result face is shared by two 3D cells, then the face in included twice in
3759  * the result mesh.
3760  *  \param [in] origin - 3 components of a point defining location of the plane.
3761  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3762  *         must be greater than 1e-6.
3763  *  \param [in] eps - half-thickness of the plane.
3764  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3765  *         producing correspondent 2D cells. The caller is to delete this array
3766  *         using decrRef() as it is no more needed.
3767  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3768  *         not share the node coordinates array with \a this mesh. The caller is to
3769  *         delete this mesh using decrRef() as it is no more needed.  
3770  *  \throw If the coordinates array is not set.
3771  *  \throw If the nodal connectivity of cells is not defined.
3772  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3773  *  \throw If magnitude of \a vec is less than 1e-6.
3774  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3775  *  \throw If \a this includes quadratic cells.
3776  */
3777 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3778 {
3779   checkFullyDefined();
3780   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3781     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3782   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3783   if(candidates->empty())
3784     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3785   std::vector<int> nodes;
3786   DataArrayInt *cellIds1D=0;
3787   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3788   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3789   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3790   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3791   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3792   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3793   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3794   revDesc2=0; revDescIndx2=0;
3795   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3796   revDesc1=0; revDescIndx1=0;
3797   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3798   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3799   //
3800   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3801   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3802     cut3DCurve[*it]=-1;
3803   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3804   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3805   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3806                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3807                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3808   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3809   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3810   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3811   if(cellIds2->empty())
3812     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3813   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3814   ret->setCoords(mDesc1->getCoords());
3815   ret->setConnectivity(conn,connI,true);
3816   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3817   return ret.retn();
3818 }
3819
3820 /*!
3821  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3822 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
3823 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3824 the result mesh.
3825  *  \param [in] origin - 3 components of a point defining location of the plane.
3826  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3827  *         must be greater than 1e-6.
3828  *  \param [in] eps - half-thickness of the plane.
3829  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3830  *         producing correspondent segments. The caller is to delete this array
3831  *         using decrRef() as it is no more needed.
3832  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3833  *         mesh in 3D space. This mesh does not share the node coordinates array with
3834  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3835  *         no more needed. 
3836  *  \throw If the coordinates array is not set.
3837  *  \throw If the nodal connectivity of cells is not defined.
3838  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3839  *  \throw If magnitude of \a vec is less than 1e-6.
3840  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3841  *  \throw If \a this includes quadratic cells.
3842  */
3843 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3844 {
3845   checkFullyDefined();
3846   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3847     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3848   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3849   if(candidates->empty())
3850     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3851   std::vector<int> nodes;
3852   DataArrayInt *cellIds1D=0;
3853   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3854   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3855   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3856   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3857   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3858   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3859   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3860   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3861   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3862   //
3863   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3864   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3865     cut3DCurve[*it]=-1;
3866   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3867   int ncellsSub=subMesh->getNumberOfCells();
3868   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3869   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3870                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3871                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3872   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3873   conn->alloc(0,1);
3874   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3875   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3876   for(int i=0;i<ncellsSub;i++)
3877     {
3878       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3879         {
3880           if(cut3DSurf[i].first!=-2)
3881             {
3882               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3883               connI->pushBackSilent(conn->getNumberOfTuples());
3884               cellIds2->pushBackSilent(i);
3885             }
3886           else
3887             {
3888               int cellId3DSurf=cut3DSurf[i].second;
3889               int offset=nodalI[cellId3DSurf]+1;
3890               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3891               for(int j=0;j<nbOfEdges;j++)
3892                 {
3893                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3894                   connI->pushBackSilent(conn->getNumberOfTuples());
3895                   cellIds2->pushBackSilent(cellId3DSurf);
3896                 }
3897             }
3898         }
3899     }
3900   if(cellIds2->empty())
3901     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3902   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3903   ret->setCoords(mDesc1->getCoords());
3904   ret->setConnectivity(conn,connI,true);
3905   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3906   return ret.retn();
3907 }
3908
3909 /*!
3910  * Finds cells whose bounding boxes intersect a given plane.
3911  *  \param [in] origin - 3 components of a point defining location of the plane.
3912  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3913  *         must be greater than 1e-6.
3914  *  \param [in] eps - half-thickness of the plane.
3915  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3916  *         cells. The caller is to delete this array using decrRef() as it is no more
3917  *         needed.
3918  *  \throw If the coordinates array is not set.
3919  *  \throw If the nodal connectivity of cells is not defined.
3920  *  \throw If \a this->getSpaceDimension() != 3.
3921  *  \throw If magnitude of \a vec is less than 1e-6.
3922  *  \sa buildSlice3D()
3923  */
3924 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3925 {
3926   checkFullyDefined();
3927   if(getSpaceDimension()!=3)
3928     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3929   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3930   if(normm<1e-6)
3931     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3932   double vec2[3];
3933   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3934   double angle=acos(vec[2]/normm);
3935   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3936   double bbox[6];
3937   if(angle>eps)
3938     {
3939       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3940       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3941       if(normm2/normm>1e-6)
3942         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3943       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3944       mw->setCoords(coo);
3945       mw->getBoundingBox(bbox);
3946       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3947       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3948     }
3949   else
3950     {
3951       getBoundingBox(bbox);
3952       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3953       cellIds=getCellsInBoundingBox(bbox,eps);
3954     }
3955   return cellIds.retn();
3956 }
3957
3958 /*!
3959  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3960  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3961  * No consideration of coordinate is done by this method.
3962  * 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)
3963  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3964  */
3965 bool MEDCouplingUMesh::isContiguous1D() const
3966 {
3967   if(getMeshDimension()!=1)
3968     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3969   int nbCells=getNumberOfCells();
3970   if(nbCells<1)
3971     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3972   const int *connI=_nodal_connec_index->getConstPointer();
3973   const int *conn=_nodal_connec->getConstPointer();
3974   int ref=conn[connI[0]+2];
3975   for(int i=1;i<nbCells;i++)
3976     {
3977       if(conn[connI[i]+1]!=ref)
3978         return false;
3979       ref=conn[connI[i]+2];
3980     }
3981   return true;
3982 }
3983
3984 /*!
3985  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3986  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3987  * \param pt reference point of the line
3988  * \param v normalized director vector of the line
3989  * \param eps max precision before throwing an exception
3990  * \param res output of size this->getNumberOfCells
3991  */
3992 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3993 {
3994   if(getMeshDimension()!=1)
3995     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3996   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3997     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3998   if(getSpaceDimension()!=3)
3999     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
4000   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
4001   const double *fPtr=f->getArray()->getConstPointer();
4002   double tmp[3];
4003   for(int i=0;i<getNumberOfCells();i++)
4004     {
4005       const double *tmp1=fPtr+3*i;
4006       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
4007       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
4008       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
4009       double n1=INTERP_KERNEL::norm<3>(tmp);
4010       n1/=INTERP_KERNEL::norm<3>(tmp1);
4011       if(n1>eps)
4012         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
4013     }
4014   const double *coo=getCoords()->getConstPointer();
4015   for(int i=0;i<getNumberOfNodes();i++)
4016     {
4017       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
4018       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
4019       res[i]=std::accumulate(tmp,tmp+3,0.);
4020     }
4021 }
4022
4023 /*!
4024  * 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. 
4025  * \a this is expected to be a mesh so that its space dimension is equal to its
4026  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4027  * 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).
4028  *
4029  * 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
4030  * 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).
4031  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4032  *
4033  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
4034  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4035  *
4036  * \param [in] ptBg the start pointer (included) of the coordinates of the point
4037  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
4038  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4039  * \return the positive value of the distance.
4040  * \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
4041  * dimension - 1.
4042  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4043  */
4044 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4045 {
4046   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4047   if(meshDim!=spaceDim-1)
4048     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4049   if(meshDim!=2 && meshDim!=1)
4050     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4051   checkFullyDefined();
4052   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4053     { 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()); }
4054   DataArrayInt *ret1=0;
4055   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4056   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4057   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4058   cellId=*ret1Safe->begin();
4059   return *ret0->begin();
4060 }
4061
4062 /*!
4063  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4064  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4065  * 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
4066  * 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).
4067  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4068  * 
4069  * \a this is expected to be a mesh so that its space dimension is equal to its
4070  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4071  * 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).
4072  *
4073  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4074  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4075  *
4076  * \param [in] pts the list of points in which each tuple represents a point
4077  * \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.
4078  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4079  * \throw if number of components of \a pts is not equal to the space dimension.
4080  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4081  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4082  */
4083 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4084 {
4085   if(!pts)
4086     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4087   pts->checkAllocated();
4088   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4089   if(meshDim!=spaceDim-1)
4090     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4091   if(meshDim!=2 && meshDim!=1)
4092     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4093   if(pts->getNumberOfComponents()!=spaceDim)
4094     {
4095       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4096       throw INTERP_KERNEL::Exception(oss.str().c_str());
4097     }
4098   checkFullyDefined();
4099   int nbCells=getNumberOfCells();
4100   if(nbCells==0)
4101     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4102   int nbOfPts=pts->getNumberOfTuples();
4103   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4104   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4105   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4106   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4107   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4108   const double *bbox(bboxArr->begin());
4109   switch(spaceDim)
4110   {
4111     case 3:
4112       {
4113         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4114         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4115           {
4116             double x=std::numeric_limits<double>::max();
4117             std::vector<int> elems;
4118             myTree.getMinDistanceOfMax(ptsPtr,x);
4119             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4120             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4121           }
4122         break;
4123       }
4124     case 2:
4125       {
4126         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4127         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4128           {
4129             double x=std::numeric_limits<double>::max();
4130             std::vector<int> elems;
4131             myTree.getMinDistanceOfMax(ptsPtr,x);
4132             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4133             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4134           }
4135         break;
4136       }
4137     default:
4138       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4139   }
4140   cellIds=ret1.retn();
4141   return ret0.retn();
4142 }
4143
4144 /*!
4145  * \param [in] pt the start pointer (included) of the coordinates of the point
4146  * \param [in] cellIdsBg the start pointer (included) of cellIds
4147  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4148  * \param [in] nc nodal connectivity
4149  * \param [in] ncI nodal connectivity index
4150  * \param [in,out] ret0 the min distance between \a this and the external input point
4151  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4152  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4153  */
4154 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)
4155 {
4156   cellId=-1;
4157   ret0=std::numeric_limits<double>::max();
4158   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4159     {
4160       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4161       {
4162         case INTERP_KERNEL::NORM_TRI3:
4163           {
4164             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4165             if(tmp<ret0)
4166               { ret0=tmp; cellId=*zeCell; }
4167             break;
4168           }
4169         case INTERP_KERNEL::NORM_QUAD4:
4170         case INTERP_KERNEL::NORM_POLYGON:
4171           {
4172             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4173             if(tmp<ret0)
4174               { ret0=tmp; cellId=*zeCell; }
4175             break;
4176           }
4177         default:
4178           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4179       }
4180     }
4181 }
4182
4183 /*!
4184  * \param [in] pt the start pointer (included) of the coordinates of the point
4185  * \param [in] cellIdsBg the start pointer (included) of cellIds
4186  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4187  * \param [in] nc nodal connectivity
4188  * \param [in] ncI nodal connectivity index
4189  * \param [in,out] ret0 the min distance between \a this and the external input point
4190  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4191  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4192  */
4193 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)
4194 {
4195   cellId=-1;
4196   ret0=std::numeric_limits<double>::max();
4197   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4198     {
4199       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4200       {
4201         case INTERP_KERNEL::NORM_SEG2:
4202           {
4203             std::size_t uselessEntry=0;
4204             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4205             tmp=sqrt(tmp);
4206             if(tmp<ret0)
4207               { ret0=tmp; cellId=*zeCell; }
4208             break;
4209           }
4210         default:
4211           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4212       }
4213     }
4214 }
4215
4216 /*!
4217  * Finds cells in contact with a ball (i.e. a point with precision). 
4218  * 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.
4219  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4220  *
4221  * \warning This method is suitable if the caller intends to evaluate only one
4222  *          point, for more points getCellsContainingPoints() is recommended as it is
4223  *          faster. 
4224  *  \param [in] pos - array of coordinates of the ball central point.
4225  *  \param [in] eps - ball radius.
4226  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4227  *         if there are no such cells.
4228  *  \throw If the coordinates array is not set.
4229  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4230  */
4231 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4232 {
4233   std::vector<int> elts;
4234   getCellsContainingPoint(pos,eps,elts);
4235   if(elts.empty())
4236     return -1;
4237   return elts.front();
4238 }
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  * \warning This method is suitable if the caller intends to evaluate only one
4245  *          point, for more points getCellsContainingPoints() is recommended as it is
4246  *          faster. 
4247  *  \param [in] pos - array of coordinates of the ball central point.
4248  *  \param [in] eps - ball radius.
4249  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4250  *         before inserting ids.
4251  *  \throw If the coordinates array is not set.
4252  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4253  *
4254  *  \if ENABLE_EXAMPLES
4255  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4256  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4257  *  \endif
4258  */
4259 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4260 {
4261   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4262   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4263   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4264 }
4265
4266 /// @cond INTERNAL
4267
4268 namespace ParaMEDMEM
4269 {
4270   template<const int SPACEDIMM>
4271   class DummyClsMCUG
4272   {
4273   public:
4274     static const int MY_SPACEDIM=SPACEDIMM;
4275     static const int MY_MESHDIM=8;
4276     typedef int MyConnType;
4277     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4278     // begin
4279     // useless, but for windows compilation ...
4280     const double* getCoordinatesPtr() const { return 0; }
4281     const int* getConnectivityPtr() const { return 0; }
4282     const int* getConnectivityIndexPtr() const { return 0; }
4283     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4284     // end
4285   };
4286
4287   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4288   {
4289     INTERP_KERNEL::Edge *ret(0);
4290     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]));
4291     m[n0]=bg[0]; m[n1]=bg[1];
4292     switch(typ)
4293     {
4294       case INTERP_KERNEL::NORM_SEG2:
4295         {
4296           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4297           break;
4298         }
4299       case INTERP_KERNEL::NORM_SEG3:
4300         {
4301           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4302           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4303           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4304           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4305           bool colinearity(inters.areColinears());
4306           delete e1; delete e2;
4307           if(colinearity)
4308             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4309           else
4310             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4311           break;
4312         }
4313       default:
4314         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4315     }
4316     return ret;
4317   }
4318
4319   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4320   {
4321     INTERP_KERNEL::Edge *ret=0;
4322     switch(typ)
4323     {
4324       case INTERP_KERNEL::NORM_SEG2:
4325         {
4326           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4327           break;
4328         }
4329       case INTERP_KERNEL::NORM_SEG3:
4330         {
4331           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4332           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4333           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4334           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4335           bool colinearity=inters.areColinears();
4336           delete e1; delete e2;
4337           if(colinearity)
4338             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4339           else
4340             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4341           mapp2[bg[2]].second=false;
4342           break;
4343         }
4344       default:
4345         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4346     }
4347     return ret;
4348   }
4349
4350   /*!
4351    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4352    * the global mesh 'mDesc'.
4353    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4354    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4355    */
4356   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4357                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4358   {
4359     mapp.clear();
4360     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.
4361     const double *coo=mDesc->getCoords()->getConstPointer();
4362     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4363     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4364     std::set<int> s;
4365     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4366       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4367     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4368       {
4369         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4370         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4371       }
4372     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4373     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4374       {
4375         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4376         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4377       }
4378     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4379       {
4380         if((*it2).second.second)
4381           mapp[(*it2).second.first]=(*it2).first;
4382         ((*it2).second.first)->decrRef();
4383       }
4384     return ret;
4385   }
4386
4387   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4388   {
4389     if(nodeId>=offset2)
4390       {
4391         int locId=nodeId-offset2;
4392         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4393       }
4394     if(nodeId>=offset1)
4395       {
4396         int locId=nodeId-offset1;
4397         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4398       }
4399     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4400   }
4401
4402   /**
4403    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4404    */
4405   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4406                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4407                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4408   {
4409     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4410       {
4411         int eltId1=abs(*desc1)-1;
4412         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4413           {
4414             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4415             if(it==mappRev.end())
4416               {
4417                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4418                 mapp[node]=*it1;
4419                 mappRev[*it1]=node;
4420               }
4421           }
4422       }
4423   }
4424 }
4425
4426 /// @endcond
4427
4428 template<int SPACEDIM>
4429 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4430                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4431 {
4432   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4433   int *eltsIndexPtr(eltsIndex->getPointer());
4434   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4435   const double *bbox(bboxArr->begin());
4436   int nbOfCells=getNumberOfCells();
4437   const int *conn=_nodal_connec->getConstPointer();
4438   const int *connI=_nodal_connec_index->getConstPointer();
4439   double bb[2*SPACEDIM];
4440   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4441   for(int i=0;i<nbOfPoints;i++)
4442     {
4443       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4444       for(int j=0;j<SPACEDIM;j++)
4445         {
4446           bb[2*j]=pos[SPACEDIM*i+j];
4447           bb[2*j+1]=pos[SPACEDIM*i+j];
4448         }
4449       std::vector<int> candidates;
4450       myTree.getIntersectingElems(bb,candidates);
4451       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4452         {
4453           int sz(connI[(*iter)+1]-connI[*iter]-1);
4454           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4455           bool status(false);
4456           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4457             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4458           else
4459             {
4460               if(SPACEDIM!=2)
4461                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4462               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4463               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4464               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4465               INTERP_KERNEL::QuadraticPolygon *pol(0);
4466               for(int j=0;j<sz;j++)
4467                 {
4468                   int nodeId(conn[connI[*iter]+1+j]);
4469                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4470                 }
4471               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4472                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4473               else
4474                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4475               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4476               double a(0.),b(0.),c(0.);
4477               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4478               status=pol->isInOrOut2(n);
4479               delete pol; n->decrRef();
4480             }
4481           if(status)
4482             {
4483               eltsIndexPtr[i+1]++;
4484               elts->pushBackSilent(*iter);
4485             }
4486         }
4487     }
4488 }
4489 /*!
4490  * Finds cells in contact with several balls (i.e. points with precision).
4491  * This method is an extension of getCellContainingPoint() and
4492  * getCellsContainingPoint() for the case of multiple points.
4493  * 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.
4494  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4495  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4496  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4497  *         this->getSpaceDimension() * \a nbOfPoints 
4498  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4499  *  \param [in] eps - radius of balls (i.e. the precision).
4500  *  \param [out] elts - vector returning ids of found cells.
4501  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4502  *         dividing cell ids in \a elts into groups each referring to one
4503  *         point. Its every element (except the last one) is an index pointing to the
4504  *         first id of a group of cells. For example cells in contact with the *i*-th
4505  *         point are described by following range of indices:
4506  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4507  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4508  *         Number of cells in contact with the *i*-th point is
4509  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4510  *  \throw If the coordinates array is not set.
4511  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4512  *
4513  *  \if ENABLE_EXAMPLES
4514  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4515  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4516  *  \endif
4517  */
4518 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4519                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4520 {
4521   int spaceDim=getSpaceDimension();
4522   int mDim=getMeshDimension();
4523   if(spaceDim==3)
4524     {
4525       if(mDim==3)
4526         {
4527           const double *coords=_coords->getConstPointer();
4528           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4529         }
4530       /*else if(mDim==2)
4531         {
4532
4533         }*/
4534       else
4535         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4536     }
4537   else if(spaceDim==2)
4538     {
4539       if(mDim==2)
4540         {
4541           const double *coords=_coords->getConstPointer();
4542           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4543         }
4544       else
4545         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4546     }
4547   else if(spaceDim==1)
4548     {
4549       if(mDim==1)
4550         {
4551           const double *coords=_coords->getConstPointer();
4552           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4553         }
4554       else
4555         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4556     }
4557   else
4558     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4559 }
4560
4561 /*!
4562  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4563  * least two its edges intersect each other anywhere except their extremities. An
4564  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4565  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4566  *         cleared before filling in.
4567  *  \param [in] eps - precision.
4568  *  \throw If \a this->getMeshDimension() != 2.
4569  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4570  */
4571 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4572 {
4573   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4574   if(getMeshDimension()!=2)
4575     throw INTERP_KERNEL::Exception(msg);
4576   int spaceDim=getSpaceDimension();
4577   if(spaceDim!=2 && spaceDim!=3)
4578     throw INTERP_KERNEL::Exception(msg);
4579   const int *conn=_nodal_connec->getConstPointer();
4580   const int *connI=_nodal_connec_index->getConstPointer();
4581   int nbOfCells=getNumberOfCells();
4582   std::vector<double> cell2DinS2;
4583   for(int i=0;i<nbOfCells;i++)
4584     {
4585       int offset=connI[i];
4586       int nbOfNodesForCell=connI[i+1]-offset-1;
4587       if(nbOfNodesForCell<=3)
4588         continue;
4589       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4590       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4591       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4592         cells.push_back(i);
4593       cell2DinS2.clear();
4594     }
4595 }
4596
4597 /*!
4598  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4599  *
4600  * 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.
4601  * 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.
4602  * 
4603  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4604  * This convex envelop is computed using Jarvis march algorithm.
4605  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4606  * 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)
4607  * 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.
4608  *
4609  * \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.
4610  * \sa MEDCouplingUMesh::colinearize2D
4611  */
4612 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4613 {
4614   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4615     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4616   checkFullyDefined();
4617   const double *coords=getCoords()->getConstPointer();
4618   int nbOfCells=getNumberOfCells();
4619   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4620   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4621   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4622   int *workIndexOut=nodalConnecIndexOut->getPointer();
4623   *workIndexOut=0;
4624   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4625   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4626   std::set<INTERP_KERNEL::NormalizedCellType> types;
4627   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4628   isChanged->alloc(0,1);
4629   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4630     {
4631       int pos=nodalConnecOut->getNumberOfTuples();
4632       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4633         isChanged->pushBackSilent(i);
4634       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4635       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4636     }
4637   if(isChanged->empty())
4638     return 0;
4639   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4640   _types=types;
4641   return isChanged.retn();
4642 }
4643
4644 /*!
4645  * This method is \b NOT const because it can modify \a this.
4646  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4647  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4648  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4649  * \b 1 for translation and rotation around point of 'mesh1D'.
4650  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4651  */
4652 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4653 {
4654   checkFullyDefined();
4655   mesh1D->checkFullyDefined();
4656   if(!mesh1D->isContiguous1D())
4657     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4658   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4659     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4660   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4661     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4662   if(mesh1D->getMeshDimension()!=1)
4663     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4664   bool isQuad=false;
4665   if(isPresenceOfQuadratic())
4666     {
4667       if(mesh1D->isFullyQuadratic())
4668         isQuad=true;
4669       else
4670         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4671     }
4672   int oldNbOfNodes(getNumberOfNodes());
4673   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4674   switch(policy)
4675   {
4676     case 0:
4677       {
4678         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4679         break;
4680       }
4681     case 1:
4682       {
4683         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4684         break;
4685       }
4686     default:
4687       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4688   }
4689   setCoords(newCoords);
4690   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4691   updateTime();
4692   return ret.retn();
4693 }
4694
4695 /*!
4696  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4697  * If it is not the case an exception will be thrown.
4698  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4699  * intersection of plane defined by ('origin','vec').
4700  * This method has one in/out parameter : 'cut3DCurve'.
4701  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4702  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4703  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4704  * This method will throw an exception if \a this contains a non linear segment.
4705  */
4706 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4707 {
4708   checkFullyDefined();
4709   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4710     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4711   int ncells=getNumberOfCells();
4712   int nnodes=getNumberOfNodes();
4713   double vec2[3],vec3[3],vec4[3];
4714   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4715   if(normm<1e-6)
4716     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4717   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4718   const int *conn=_nodal_connec->getConstPointer();
4719   const int *connI=_nodal_connec_index->getConstPointer();
4720   const double *coo=_coords->getConstPointer();
4721   std::vector<double> addCoo;
4722   for(int i=0;i<ncells;i++)
4723     {
4724       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4725         {
4726           if(cut3DCurve[i]==-2)
4727             {
4728               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4729               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];
4730               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4731               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4732               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4733                 {
4734                   const double *st2=coo+3*st;
4735                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4736                   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]));
4737                   if(pos>eps && pos<1-eps)
4738                     {
4739                       int nNode=((int)addCoo.size())/3;
4740                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4741                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4742                       cut3DCurve[i]=nnodes+nNode;
4743                     }
4744                 }
4745             }
4746         }
4747       else
4748         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4749     }
4750   if(!addCoo.empty())
4751     {
4752       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4753       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4754       coo2->alloc(newNbOfNodes,3);
4755       double *tmp=coo2->getPointer();
4756       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4757       std::copy(addCoo.begin(),addCoo.end(),tmp);
4758       DataArrayDouble::SetArrayIn(coo2,_coords);
4759     }
4760 }
4761
4762 /*!
4763  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4764  * \param mesh1D is the input 1D mesh used for translation computation.
4765  * \return newCoords new coords filled by this method. 
4766  */
4767 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4768 {
4769   int oldNbOfNodes=getNumberOfNodes();
4770   int nbOf1DCells=mesh1D->getNumberOfCells();
4771   int spaceDim=getSpaceDimension();
4772   DataArrayDouble *ret=DataArrayDouble::New();
4773   std::vector<bool> isQuads;
4774   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4775   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4776   double *retPtr=ret->getPointer();
4777   const double *coords=getCoords()->getConstPointer();
4778   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4779   std::vector<int> v;
4780   std::vector<double> c;
4781   double vec[3];
4782   v.reserve(3);
4783   c.reserve(6);
4784   for(int i=0;i<nbOf1DCells;i++)
4785     {
4786       v.resize(0);
4787       mesh1D->getNodeIdsOfCell(i,v);
4788       c.resize(0);
4789       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4790       mesh1D->getCoordinatesOfNode(v[0],c);
4791       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4792       for(int j=0;j<oldNbOfNodes;j++)
4793         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4794       if(isQuad)
4795         {
4796           c.resize(0);
4797           mesh1D->getCoordinatesOfNode(v[1],c);
4798           mesh1D->getCoordinatesOfNode(v[0],c);
4799           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4800           for(int j=0;j<oldNbOfNodes;j++)
4801             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4802         }
4803     }
4804   ret->copyStringInfoFrom(*getCoords());
4805   return ret;
4806 }
4807
4808 /*!
4809  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4810  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4811  * \return newCoords new coords filled by this method. 
4812  */
4813 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4814 {
4815   if(mesh1D->getSpaceDimension()==2)
4816     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4817   if(mesh1D->getSpaceDimension()==3)
4818     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4819   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4820 }
4821
4822 /*!
4823  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4824  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4825  * \return newCoords new coords filled by this method. 
4826  */
4827 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4828 {
4829   if(isQuad)
4830     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4831   int oldNbOfNodes=getNumberOfNodes();
4832   int nbOf1DCells=mesh1D->getNumberOfCells();
4833   if(nbOf1DCells<2)
4834     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4835   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4836   int nbOfLevsInVec=nbOf1DCells+1;
4837   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4838   double *retPtr=ret->getPointer();
4839   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4840   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4841   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4842   tmp->setCoords(tmp2);
4843   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4844   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4845   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4846   for(int i=1;i<nbOfLevsInVec;i++)
4847     {
4848       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4849       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4850       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4851       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4852       tmp->translate(vec);
4853       double tmp3[2],radius,alpha,alpha0;
4854       const double *p0=i+1<nbOfLevsInVec?begin:third;
4855       const double *p1=i+1<nbOfLevsInVec?end:begin;
4856       const double *p2=i+1<nbOfLevsInVec?third:end;
4857       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4858       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]);
4859       double angle=acos(cosangle/(radius*radius));
4860       tmp->rotate(end,0,angle);
4861       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4862     }
4863   return ret.retn();
4864 }
4865
4866 /*!
4867  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4868  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4869  * \return newCoords new coords filled by this method. 
4870  */
4871 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4872 {
4873   if(isQuad)
4874     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4875   int oldNbOfNodes=getNumberOfNodes();
4876   int nbOf1DCells=mesh1D->getNumberOfCells();
4877   if(nbOf1DCells<2)
4878     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4879   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4880   int nbOfLevsInVec=nbOf1DCells+1;
4881   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4882   double *retPtr=ret->getPointer();
4883   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4884   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4885   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4886   tmp->setCoords(tmp2);
4887   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4888   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4889   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4890   for(int i=1;i<nbOfLevsInVec;i++)
4891     {
4892       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4893       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4894       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4895       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4896       tmp->translate(vec);
4897       double tmp3[2],radius,alpha,alpha0;
4898       const double *p0=i+1<nbOfLevsInVec?begin:third;
4899       const double *p1=i+1<nbOfLevsInVec?end:begin;
4900       const double *p2=i+1<nbOfLevsInVec?third:end;
4901       double vecPlane[3]={
4902         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4903         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4904         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4905       };
4906       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4907       if(norm>1.e-7)
4908         {
4909           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4910           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4911           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4912           double s2=norm2;
4913           double c2=cos(asin(s2));
4914           double m[3][3]={
4915             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4916             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4917             {-vec2[1]*s2, vec2[0]*s2, c2}
4918           };
4919           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]};
4920           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]};
4921           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]};
4922           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4923           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]);
4924           double angle=acos(cosangle/(radius*radius));
4925           tmp->rotate(end,vecPlane,angle);
4926         }
4927       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4928     }
4929   return ret.retn();
4930 }
4931
4932 /*!
4933  * This method is private because not easy to use for end user. This method is const contrary to
4934  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4935  * the coords sorted slice by slice.
4936  * \param isQuad specifies presence of quadratic cells.
4937  */
4938 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4939 {
4940   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4941   int nbOf2DCells(getNumberOfCells());
4942   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4943   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4944   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4945   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4946   newConnI->alloc(nbOf3DCells+1,1);
4947   int *newConnIPtr(newConnI->getPointer());
4948   *newConnIPtr++=0;
4949   std::vector<int> newc;
4950   for(int j=0;j<nbOf2DCells;j++)
4951     {
4952       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4953       *newConnIPtr++=(int)newc.size();
4954     }
4955   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4956   int *newConnPtr(newConn->getPointer());
4957   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4958   newConnIPtr=newConnI->getPointer();
4959   for(int iz=0;iz<nbOf1DCells;iz++)
4960     {
4961       if(iz!=0)
4962         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4963       const int *posOfTypeOfCell(newConnIPtr);
4964       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4965         {
4966           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4967           if(icell!=*posOfTypeOfCell)
4968             {
4969               if(*iter!=-1)
4970                 *newConnPtr=(*iter)+iz*deltaPerLev;
4971               else
4972                 *newConnPtr=-1;
4973             }
4974           else
4975             {
4976               *newConnPtr=*iter;
4977               posOfTypeOfCell++;
4978             }
4979         }
4980     }
4981   ret->setConnectivity(newConn,newConnI,true);
4982   ret->setCoords(getCoords());
4983   return ret;
4984 }
4985
4986 /*!
4987  * Checks if \a this mesh is constituted by only quadratic cells.
4988  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4989  *  \throw If the coordinates array is not set.
4990  *  \throw If the nodal connectivity of cells is not defined.
4991  */
4992 bool MEDCouplingUMesh::isFullyQuadratic() const
4993 {
4994   checkFullyDefined();
4995   bool ret=true;
4996   int nbOfCells=getNumberOfCells();
4997   for(int i=0;i<nbOfCells && ret;i++)
4998     {
4999       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5000       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5001       ret=cm.isQuadratic();
5002     }
5003   return ret;
5004 }
5005
5006 /*!
5007  * Checks if \a this mesh includes any quadratic cell.
5008  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
5009  *  \throw If the coordinates array is not set.
5010  *  \throw If the nodal connectivity of cells is not defined.
5011  */
5012 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
5013 {
5014   checkFullyDefined();
5015   bool ret=false;
5016   int nbOfCells=getNumberOfCells();
5017   for(int i=0;i<nbOfCells && !ret;i++)
5018     {
5019       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5020       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5021       ret=cm.isQuadratic();
5022     }
5023   return ret;
5024 }
5025
5026 /*!
5027  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
5028  * this mesh, it remains unchanged.
5029  *  \throw If the coordinates array is not set.
5030  *  \throw If the nodal connectivity of cells is not defined.
5031  */
5032 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
5033 {
5034   checkFullyDefined();
5035   int nbOfCells=getNumberOfCells();
5036   int delta=0;
5037   const int *iciptr=_nodal_connec_index->getConstPointer();
5038   for(int i=0;i<nbOfCells;i++)
5039     {
5040       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5041       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5042       if(cm.isQuadratic())
5043         {
5044           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5045           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5046           if(!cml.isDynamic())
5047             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5048           else
5049             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5050         }
5051     }
5052   if(delta==0)
5053     return ;
5054   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5055   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5056   const int *icptr=_nodal_connec->getConstPointer();
5057   newConn->alloc(getMeshLength()-delta,1);
5058   newConnI->alloc(nbOfCells+1,1);
5059   int *ocptr=newConn->getPointer();
5060   int *ociptr=newConnI->getPointer();
5061   *ociptr=0;
5062   _types.clear();
5063   for(int i=0;i<nbOfCells;i++,ociptr++)
5064     {
5065       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5066       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5067       if(!cm.isQuadratic())
5068         {
5069           _types.insert(type);
5070           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5071           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5072         }
5073       else
5074         {
5075           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5076           _types.insert(typel);
5077           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5078           int newNbOfNodes=cml.getNumberOfNodes();
5079           if(cml.isDynamic())
5080             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5081           *ocptr++=(int)typel;
5082           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5083           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5084         }
5085     }
5086   setConnectivity(newConn,newConnI,false);
5087 }
5088
5089 /*!
5090  * This method converts all linear cell in \a this to quadratic one.
5091  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5092  * 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)
5093  * 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.
5094  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5095  * end of the existing coordinates.
5096  * 
5097  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5098  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5099  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5100  * 
5101  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5102  *
5103  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5104  */
5105 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5106 {
5107   DataArrayInt *conn=0,*connI=0;
5108   DataArrayDouble *coords=0;
5109   std::set<INTERP_KERNEL::NormalizedCellType> types;
5110   checkFullyDefined();
5111   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5112   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5113   int meshDim=getMeshDimension();
5114   switch(conversionType)
5115   {
5116     case 0:
5117       switch(meshDim)
5118       {
5119         case 1:
5120           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5121           connSafe=conn; connISafe=connI; coordsSafe=coords;
5122           break;
5123         case 2:
5124           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5125           connSafe=conn; connISafe=connI; coordsSafe=coords;
5126           break;
5127         case 3:
5128           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5129           connSafe=conn; connISafe=connI; coordsSafe=coords;
5130           break;
5131         default:
5132           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5133       }
5134       break;
5135         case 1:
5136           {
5137             switch(meshDim)
5138             {
5139               case 1:
5140                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5141                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5142                 break;
5143               case 2:
5144                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5145                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5146                 break;
5147               case 3:
5148                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5149                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5150                 break;
5151               default:
5152                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5153             }
5154             break;
5155           }
5156         default:
5157           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5158   }
5159   setConnectivity(connSafe,connISafe,false);
5160   _types=types;
5161   setCoords(coordsSafe);
5162   return ret.retn();
5163 }
5164
5165 #if 0
5166 /*!
5167  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5168  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5169  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5170  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5171  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5172  * This method can be seen as the opposite method of colinearize2D.
5173  * 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
5174  * to avoid to modify the numbering of existing nodes.
5175  *
5176  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5177  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5178  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5179  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5180  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5181  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5182  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5183  *
5184  * \sa buildDescendingConnectivity2
5185  */
5186 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5187                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5188 {
5189   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5190     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5191   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5192   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5193     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5194   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5195     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5196   //DataArrayInt *out0(0),*outi0(0);
5197   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5198   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5199   //out0s=out0s->buildUnique(); out0s->sort(true);
5200 }
5201 #endif
5202
5203 /*!
5204  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5205  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5206  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5207  */
5208 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5209 {
5210   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5211   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5212   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5213   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5214   int nbOfCells=getNumberOfCells();
5215   int nbOfNodes=getNumberOfNodes();
5216   const int *cPtr=_nodal_connec->getConstPointer();
5217   const int *icPtr=_nodal_connec_index->getConstPointer();
5218   int lastVal=0,offset=nbOfNodes;
5219   for(int i=0;i<nbOfCells;i++,icPtr++)
5220     {
5221       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5222       if(type==INTERP_KERNEL::NORM_SEG2)
5223         {
5224           types.insert(INTERP_KERNEL::NORM_SEG3);
5225           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5226           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5227           newConn->pushBackSilent(offset++);
5228           lastVal+=4;
5229           newConnI->pushBackSilent(lastVal);
5230           ret->pushBackSilent(i);
5231         }
5232       else
5233         {
5234           types.insert(type);
5235           lastVal+=(icPtr[1]-icPtr[0]);
5236           newConnI->pushBackSilent(lastVal);
5237           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5238         }
5239     }
5240   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5241   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5242   return ret.retn();
5243 }
5244
5245 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
5246 {
5247   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5248   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5249   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5250   //
5251   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5252   DataArrayInt *conn1D=0,*conn1DI=0;
5253   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5254   DataArrayDouble *coordsTmp=0;
5255   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5256   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5257   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5258   const int *c1DPtr=conn1D->begin();
5259   const int *c1DIPtr=conn1DI->begin();
5260   int nbOfCells=getNumberOfCells();
5261   const int *cPtr=_nodal_connec->getConstPointer();
5262   const int *icPtr=_nodal_connec_index->getConstPointer();
5263   int lastVal=0;
5264   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5265     {
5266       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5267       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5268       if(!cm.isQuadratic())
5269         {
5270           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5271           types.insert(typ2); newConn->pushBackSilent(typ2);
5272           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5273           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5274             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5275           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5276           newConnI->pushBackSilent(lastVal);
5277           ret->pushBackSilent(i);
5278         }
5279       else
5280         {
5281           types.insert(typ);
5282           lastVal+=(icPtr[1]-icPtr[0]);
5283           newConnI->pushBackSilent(lastVal);
5284           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5285         }
5286     }
5287   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5288   return ret.retn();
5289 }
5290
5291 /*!
5292  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5293  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5294  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5295  */
5296 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5297 {
5298   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5299   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5300   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5301 }
5302
5303 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5304 {
5305   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5306   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5307   //
5308   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5309   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5310   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5311   //
5312   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5313   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5314   DataArrayInt *conn1D=0,*conn1DI=0;
5315   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5316   DataArrayDouble *coordsTmp=0;
5317   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5318   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5319   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5320   const int *c1DPtr=conn1D->begin();
5321   const int *c1DIPtr=conn1DI->begin();
5322   int nbOfCells=getNumberOfCells();
5323   const int *cPtr=_nodal_connec->getConstPointer();
5324   const int *icPtr=_nodal_connec_index->getConstPointer();
5325   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5326   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5327     {
5328       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5329       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5330       if(!cm.isQuadratic())
5331         {
5332           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5333           types.insert(typ2); newConn->pushBackSilent(typ2);
5334           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5335           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5336             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5337           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5338           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5339           newConnI->pushBackSilent(lastVal);
5340           ret->pushBackSilent(i);
5341         }
5342       else
5343         {
5344           types.insert(typ);
5345           lastVal+=(icPtr[1]-icPtr[0]);
5346           newConnI->pushBackSilent(lastVal);
5347           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5348         }
5349     }
5350   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5351   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5352   return ret.retn();
5353 }
5354
5355 /*!
5356  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5357  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5358  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5359  */
5360 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5361 {
5362   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5363   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5364   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5365 }
5366
5367 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5368 {
5369   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5370   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5371   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5372   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5373   //
5374   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5375   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5376   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5377   //
5378   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5379   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5380   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5381   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5382   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5383   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5384   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5385   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5386   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5387   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5389   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5390   int nbOfCells=getNumberOfCells();
5391   const int *cPtr=_nodal_connec->getConstPointer();
5392   const int *icPtr=_nodal_connec_index->getConstPointer();
5393   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5394   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5395     {
5396       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5397       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5398       if(!cm.isQuadratic())
5399         {
5400           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5401           if(typ2==INTERP_KERNEL::NORM_ERROR)
5402             {
5403               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5404               throw INTERP_KERNEL::Exception(oss.str().c_str());
5405             }
5406           types.insert(typ2); newConn->pushBackSilent(typ2);
5407           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5408           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5409             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5410           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5411             {
5412               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5413               int tmpPos=newConn->getNumberOfTuples();
5414               newConn->pushBackSilent(nodeId2);
5415               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5416             }
5417           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5418           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5419           newConnI->pushBackSilent(lastVal);
5420           ret->pushBackSilent(i);
5421         }
5422       else
5423         {
5424           types.insert(typ);
5425           lastVal+=(icPtr[1]-icPtr[0]);
5426           newConnI->pushBackSilent(lastVal);
5427           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5428         }
5429     }
5430   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5432   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5433   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5434   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5435   int *c=newConn->getPointer();
5436   const int *cI(newConnI->begin());
5437   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5438     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5439   offset=coordsTmp2Safe->getNumberOfTuples();
5440   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5441     c[cI[(*elt)+1]-1]+=offset;
5442   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5443   return ret.retn();
5444 }
5445
5446 /*!
5447  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5448  * so that the number of cells remains the same. Quadratic faces are converted to
5449  * polygons. This method works only for 2D meshes in
5450  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5451  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5452  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5453  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5454  *         a polylinized edge constituting the input polygon.
5455  *  \throw If the coordinates array is not set.
5456  *  \throw If the nodal connectivity of cells is not defined.
5457  *  \throw If \a this->getMeshDimension() != 2.
5458  *  \throw If \a this->getSpaceDimension() != 2.
5459  */
5460 void MEDCouplingUMesh::tessellate2D(double eps)
5461 {
5462   checkFullyDefined();
5463   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5464     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5465   double epsa=fabs(eps);
5466   if(epsa<std::numeric_limits<double>::min())
5467     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 !");
5468   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5469   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5470   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5471   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5472   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5473   revDesc1=0; revDescIndx1=0;
5474   mDesc->tessellate2DCurve(eps);
5475   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5476   setCoords(mDesc->getCoords());
5477 }
5478
5479 /*!
5480  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
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 radian) between 2 sub-edges of
5483  *         a sub-divided edge.
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() != 1.
5487  *  \throw If \a this->getSpaceDimension() != 2.
5488  */
5489 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5490 {
5491   checkFullyDefined();
5492   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5493     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 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   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5498   int nbCells=getNumberOfCells();
5499   int nbNodes=getNumberOfNodes();
5500   const int *conn=_nodal_connec->getConstPointer();
5501   const int *connI=_nodal_connec_index->getConstPointer();
5502   const double *coords=_coords->getConstPointer();
5503   std::vector<double> addCoo;
5504   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5505   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5506   newConnI->alloc(nbCells+1,1);
5507   int *newConnIPtr=newConnI->getPointer();
5508   *newConnIPtr=0;
5509   int tmp1[3];
5510   INTERP_KERNEL::Node *tmp2[3];
5511   std::set<INTERP_KERNEL::NormalizedCellType> types;
5512   for(int i=0;i<nbCells;i++,newConnIPtr++)
5513     {
5514       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5515       if(cm.isQuadratic())
5516         {//assert(connI[i+1]-connI[i]-1==3)
5517           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5518           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5519           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5520           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5521           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5522           if(eac)
5523             {
5524               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5525               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5526               delete eac;
5527               newConnIPtr[1]=(int)newConn.size();
5528             }
5529           else
5530             {
5531               types.insert(INTERP_KERNEL::NORM_SEG2);
5532               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5533               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5534               newConnIPtr[1]=newConnIPtr[0]+3;
5535             }
5536         }
5537       else
5538         {
5539           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5540           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5541           newConnIPtr[1]=newConnIPtr[0]+3;
5542         }
5543     }
5544   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5545     return ;
5546   _types=types;
5547   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5548   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5549   newConnArr->alloc((int)newConn.size(),1);
5550   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5551   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5552   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5553   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5554   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5555   std::copy(addCoo.begin(),addCoo.end(),work);
5556   DataArrayDouble::SetArrayIn(newCoords,_coords);
5557   updateTime();
5558 }
5559
5560 /*!
5561  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5562  * In addition, returns an array mapping new cells to old ones. <br>
5563  * This method typically increases the number of cells in \a this mesh
5564  * but the number of nodes remains \b unchanged.
5565  * That's why the 3D splitting policies
5566  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5567  *  \param [in] policy - specifies a pattern used for splitting.
5568  * The semantic of \a policy is:
5569  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5570  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5571  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5572  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5573  *
5574  *
5575  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5576  *          an id of old cell producing it. The caller is to delete this array using
5577  *         decrRef() as it is no more needed.
5578  *
5579  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5580  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5581  *          and \a this->getMeshDimension() != 3. 
5582  *  \throw If \a policy is not one of the four discussed above.
5583  *  \throw If the nodal connectivity of cells is not defined.
5584  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5585  */
5586 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5587 {
5588   switch(policy)
5589   {
5590     case 0:
5591       return simplexizePol0();
5592     case 1:
5593       return simplexizePol1();
5594     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5595         return simplexizePlanarFace5();
5596     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5597         return simplexizePlanarFace6();
5598     default:
5599       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)");
5600   }
5601 }
5602
5603 /*!
5604  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5605  * - 1D: INTERP_KERNEL::NORM_SEG2
5606  * - 2D: INTERP_KERNEL::NORM_TRI3
5607  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5608  *
5609  * This method is useful for users that need to use P1 field services as
5610  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5611  * All these methods need mesh support containing only simplex cells.
5612  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5613  *  \throw If the coordinates array is not set.
5614  *  \throw If the nodal connectivity of cells is not defined.
5615  *  \throw If \a this->getMeshDimension() < 1.
5616  */
5617 bool MEDCouplingUMesh::areOnlySimplexCells() const
5618 {
5619   checkFullyDefined();
5620   int mdim=getMeshDimension();
5621   if(mdim<1 || mdim>3)
5622     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5623   int nbCells=getNumberOfCells();
5624   const int *conn=_nodal_connec->getConstPointer();
5625   const int *connI=_nodal_connec_index->getConstPointer();
5626   for(int i=0;i<nbCells;i++)
5627     {
5628       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5629       if(!cm.isSimplex())
5630         return false;
5631     }
5632   return true;
5633 }
5634
5635 /*!
5636  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5637  */
5638 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5639 {
5640   checkConnectivityFullyDefined();
5641   if(getMeshDimension()!=2)
5642     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5643   int nbOfCells=getNumberOfCells();
5644   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5645   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5646   ret->alloc(nbOfCells+nbOfCutCells,1);
5647   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5648   int *retPt=ret->getPointer();
5649   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5650   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5651   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5652   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5653   int *pt=newConn->getPointer();
5654   int *ptI=newConnI->getPointer();
5655   ptI[0]=0;
5656   const int *oldc=_nodal_connec->getConstPointer();
5657   const int *ci=_nodal_connec_index->getConstPointer();
5658   for(int i=0;i<nbOfCells;i++,ci++)
5659     {
5660       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5661         {
5662           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5663             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5664           pt=std::copy(tmp,tmp+8,pt);
5665           ptI[1]=ptI[0]+4;
5666           ptI[2]=ptI[0]+8;
5667           *retPt++=i;
5668           *retPt++=i;
5669           ptI+=2;
5670         }
5671       else
5672         {
5673           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5674           ptI[1]=ptI[0]+ci[1]-ci[0];
5675           ptI++;
5676           *retPt++=i;
5677         }
5678     }
5679   _nodal_connec->decrRef();
5680   _nodal_connec=newConn.retn();
5681   _nodal_connec_index->decrRef();
5682   _nodal_connec_index=newConnI.retn();
5683   computeTypes();
5684   updateTime();
5685   return ret.retn();
5686 }
5687
5688 /*!
5689  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5690  */
5691 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5692 {
5693   checkConnectivityFullyDefined();
5694   if(getMeshDimension()!=2)
5695     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5696   int nbOfCells=getNumberOfCells();
5697   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5698   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5699   ret->alloc(nbOfCells+nbOfCutCells,1);
5700   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5701   int *retPt=ret->getPointer();
5702   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5703   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5704   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5705   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5706   int *pt=newConn->getPointer();
5707   int *ptI=newConnI->getPointer();
5708   ptI[0]=0;
5709   const int *oldc=_nodal_connec->getConstPointer();
5710   const int *ci=_nodal_connec_index->getConstPointer();
5711   for(int i=0;i<nbOfCells;i++,ci++)
5712     {
5713       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5714         {
5715           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5716             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5717           pt=std::copy(tmp,tmp+8,pt);
5718           ptI[1]=ptI[0]+4;
5719           ptI[2]=ptI[0]+8;
5720           *retPt++=i;
5721           *retPt++=i;
5722           ptI+=2;
5723         }
5724       else
5725         {
5726           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5727           ptI[1]=ptI[0]+ci[1]-ci[0];
5728           ptI++;
5729           *retPt++=i;
5730         }
5731     }
5732   _nodal_connec->decrRef();
5733   _nodal_connec=newConn.retn();
5734   _nodal_connec_index->decrRef();
5735   _nodal_connec_index=newConnI.retn();
5736   computeTypes();
5737   updateTime();
5738   return ret.retn();
5739 }
5740
5741 /*!
5742  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5743  */
5744 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5745 {
5746   checkConnectivityFullyDefined();
5747   if(getMeshDimension()!=3)
5748     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5749   int nbOfCells=getNumberOfCells();
5750   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5751   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5752   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5753   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5754   int *retPt=ret->getPointer();
5755   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5756   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5757   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5758   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5759   int *pt=newConn->getPointer();
5760   int *ptI=newConnI->getPointer();
5761   ptI[0]=0;
5762   const int *oldc=_nodal_connec->getConstPointer();
5763   const int *ci=_nodal_connec_index->getConstPointer();
5764   for(int i=0;i<nbOfCells;i++,ci++)
5765     {
5766       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5767         {
5768           for(int j=0;j<5;j++,pt+=5,ptI++)
5769             {
5770               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5771               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];
5772               *retPt++=i;
5773               ptI[1]=ptI[0]+5;
5774             }
5775         }
5776       else
5777         {
5778           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5779           ptI[1]=ptI[0]+ci[1]-ci[0];
5780           ptI++;
5781           *retPt++=i;
5782         }
5783     }
5784   _nodal_connec->decrRef();
5785   _nodal_connec=newConn.retn();
5786   _nodal_connec_index->decrRef();
5787   _nodal_connec_index=newConnI.retn();
5788   computeTypes();
5789   updateTime();
5790   return ret.retn();
5791 }
5792
5793 /*!
5794  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5795  */
5796 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5797 {
5798   checkConnectivityFullyDefined();
5799   if(getMeshDimension()!=3)
5800     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5801   int nbOfCells=getNumberOfCells();
5802   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5803   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5804   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5805   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5806   int *retPt=ret->getPointer();
5807   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5808   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5809   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5810   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5811   int *pt=newConn->getPointer();
5812   int *ptI=newConnI->getPointer();
5813   ptI[0]=0;
5814   const int *oldc=_nodal_connec->getConstPointer();
5815   const int *ci=_nodal_connec_index->getConstPointer();
5816   for(int i=0;i<nbOfCells;i++,ci++)
5817     {
5818       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5819         {
5820           for(int j=0;j<6;j++,pt+=5,ptI++)
5821             {
5822               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5823               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];
5824               *retPt++=i;
5825               ptI[1]=ptI[0]+5;
5826             }
5827         }
5828       else
5829         {
5830           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5831           ptI[1]=ptI[0]+ci[1]-ci[0];
5832           ptI++;
5833           *retPt++=i;
5834         }
5835     }
5836   _nodal_connec->decrRef();
5837   _nodal_connec=newConn.retn();
5838   _nodal_connec_index->decrRef();
5839   _nodal_connec_index=newConnI.retn();
5840   computeTypes();
5841   updateTime();
5842   return ret.retn();
5843 }
5844
5845 /*!
5846  * 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.
5847  * This method completly ignore coordinates.
5848  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5849  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5850  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5851  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5852  */
5853 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5854 {
5855   checkFullyDefined();
5856   if(getMeshDimension()!=2)
5857     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5858   int nbOfCells=getNumberOfCells();
5859   int *connI=_nodal_connec_index->getPointer();
5860   int newConnLgth=0;
5861   for(int i=0;i<nbOfCells;i++,connI++)
5862     {
5863       int offset=descIndex[i];
5864       int nbOfEdges=descIndex[i+1]-offset;
5865       //
5866       bool ddirect=desc[offset+nbOfEdges-1]>0;
5867       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5868       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5869       for(int j=0;j<nbOfEdges;j++)
5870         {
5871           bool direct=desc[offset+j]>0;
5872           int edgeId=std::abs(desc[offset+j])-1;
5873           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5874             {
5875               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5876               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5877               int ref2=direct?id1:id2;
5878               if(ref==ref2)
5879                 {
5880                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5881                   newConnLgth+=nbOfSubNodes-1;
5882                   ref=direct?id2:id1;
5883                 }
5884               else
5885                 {
5886                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5887                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5888                 }
5889             }
5890           else
5891             {
5892               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5893             }
5894         }
5895       newConnLgth++;//+1 is for cell type
5896       connI[1]=newConnLgth;
5897     }
5898   //
5899   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5900   newConn->alloc(newConnLgth,1);
5901   int *work=newConn->getPointer();
5902   for(int i=0;i<nbOfCells;i++)
5903     {
5904       *work++=INTERP_KERNEL::NORM_POLYGON;
5905       int offset=descIndex[i];
5906       int nbOfEdges=descIndex[i+1]-offset;
5907       for(int j=0;j<nbOfEdges;j++)
5908         {
5909           bool direct=desc[offset+j]>0;
5910           int edgeId=std::abs(desc[offset+j])-1;
5911           if(direct)
5912             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5913           else
5914             {
5915               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5916               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5917               work=std::copy(it,it+nbOfSubNodes-1,work);
5918             }
5919         }
5920     }
5921   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5922   _types.clear();
5923   if(nbOfCells>0)
5924     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5925 }
5926
5927 /*!
5928  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5929  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5930  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5931  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5932  * so it can be useful to call mergeNodes() before calling this method.
5933  *  \throw If \a this->getMeshDimension() <= 1.
5934  *  \throw If the coordinates array is not set.
5935  *  \throw If the nodal connectivity of cells is not defined.
5936  */
5937 void MEDCouplingUMesh::convertDegeneratedCells()
5938 {
5939   checkFullyDefined();
5940   if(getMeshDimension()<=1)
5941     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5942   int nbOfCells=getNumberOfCells();
5943   if(nbOfCells<1)
5944     return ;
5945   int initMeshLgth=getMeshLength();
5946   int *conn=_nodal_connec->getPointer();
5947   int *index=_nodal_connec_index->getPointer();
5948   int posOfCurCell=0;
5949   int newPos=0;
5950   int lgthOfCurCell;
5951   for(int i=0;i<nbOfCells;i++)
5952     {
5953       lgthOfCurCell=index[i+1]-posOfCurCell;
5954       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5955       int newLgth;
5956       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5957                                                                                                      conn+newPos+1,newLgth);
5958       conn[newPos]=newType;
5959       newPos+=newLgth+1;
5960       posOfCurCell=index[i+1];
5961       index[i+1]=newPos;
5962     }
5963   if(newPos!=initMeshLgth)
5964     _nodal_connec->reAlloc(newPos);
5965   computeTypes();
5966 }
5967
5968 /*!
5969  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5970  * A cell is considered to be oriented correctly if an angle between its
5971  * normal vector and a given vector is less than \c PI / \c 2.
5972  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5973  *         cells. 
5974  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5975  *         checked.
5976  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5977  *         is not cleared before filling in.
5978  *  \throw If \a this->getMeshDimension() != 2.
5979  *  \throw If \a this->getSpaceDimension() != 3.
5980  *
5981  *  \if ENABLE_EXAMPLES
5982  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5983  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5984  *  \endif
5985  */
5986 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5987 {
5988   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5989     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5990   int nbOfCells=getNumberOfCells();
5991   const int *conn=_nodal_connec->getConstPointer();
5992   const int *connI=_nodal_connec_index->getConstPointer();
5993   const double *coordsPtr=_coords->getConstPointer();
5994   for(int i=0;i<nbOfCells;i++)
5995     {
5996       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5997       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5998         {
5999           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
6000           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6001             cells.push_back(i);
6002         }
6003     }
6004 }
6005
6006 /*!
6007  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
6008  * considered to be oriented correctly if an angle between its normal vector and a
6009  * given vector is less than \c PI / \c 2. 
6010  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
6011  *         cells. 
6012  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
6013  *         checked.
6014  *  \throw If \a this->getMeshDimension() != 2.
6015  *  \throw If \a this->getSpaceDimension() != 3.
6016  *
6017  *  \if ENABLE_EXAMPLES
6018  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
6019  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
6020  *  \endif
6021  *
6022  *  \sa changeOrientationOfCells
6023  */
6024 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
6025 {
6026   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6027     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
6028   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6029   const int *connI(_nodal_connec_index->getConstPointer());
6030   const double *coordsPtr(_coords->getConstPointer());
6031   bool isModified(false);
6032   for(int i=0;i<nbOfCells;i++)
6033     {
6034       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6035       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
6036         {
6037           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6038           bool isQuadratic(cm.isQuadratic());
6039           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6040             {
6041               isModified=true;
6042               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6043             }
6044         }
6045     }
6046   if(isModified)
6047     _nodal_connec->declareAsNew();
6048   updateTime();
6049 }
6050
6051 /*!
6052  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6053  *
6054  * \sa orientCorrectly2DCells
6055  */
6056 void MEDCouplingUMesh::changeOrientationOfCells()
6057 {
6058   int mdim(getMeshDimension());
6059   if(mdim!=2 && mdim!=1)
6060     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6061   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6062   const int *connI(_nodal_connec_index->getConstPointer());
6063   if(mdim==2)
6064     {//2D
6065       for(int i=0;i<nbOfCells;i++)
6066         {
6067           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6068           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6069           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6070         }
6071     }
6072   else
6073     {//1D
6074       for(int i=0;i<nbOfCells;i++)
6075         {
6076           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6077           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6078           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6079         }
6080     }
6081 }
6082
6083 /*!
6084  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6085  * oriented facets. The normal vector of the facet should point out of the cell.
6086  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6087  *         is not cleared before filling in.
6088  *  \throw If \a this->getMeshDimension() != 3.
6089  *  \throw If \a this->getSpaceDimension() != 3.
6090  *  \throw If the coordinates array is not set.
6091  *  \throw If the nodal connectivity of cells is not defined.
6092  *
6093  *  \if ENABLE_EXAMPLES
6094  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6095  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6096  *  \endif
6097  */
6098 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6099 {
6100   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6101     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6102   int nbOfCells=getNumberOfCells();
6103   const int *conn=_nodal_connec->getConstPointer();
6104   const int *connI=_nodal_connec_index->getConstPointer();
6105   const double *coordsPtr=_coords->getConstPointer();
6106   for(int i=0;i<nbOfCells;i++)
6107     {
6108       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6109       if(type==INTERP_KERNEL::NORM_POLYHED)
6110         {
6111           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6112             cells.push_back(i);
6113         }
6114     }
6115 }
6116
6117 /*!
6118  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6119  * out of the cell. 
6120  *  \throw If \a this->getMeshDimension() != 3.
6121  *  \throw If \a this->getSpaceDimension() != 3.
6122  *  \throw If the coordinates array is not set.
6123  *  \throw If the nodal connectivity of cells is not defined.
6124  *  \throw If the reparation fails.
6125  *
6126  *  \if ENABLE_EXAMPLES
6127  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6128  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6129  *  \endif
6130  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6131  */
6132 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6133 {
6134   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6135     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6136   int nbOfCells=getNumberOfCells();
6137   int *conn=_nodal_connec->getPointer();
6138   const int *connI=_nodal_connec_index->getConstPointer();
6139   const double *coordsPtr=_coords->getConstPointer();
6140   for(int i=0;i<nbOfCells;i++)
6141     {
6142       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6143       if(type==INTERP_KERNEL::NORM_POLYHED)
6144         {
6145           try
6146           {
6147               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6148                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6149           }
6150           catch(INTERP_KERNEL::Exception& e)
6151           {
6152               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6153               throw INTERP_KERNEL::Exception(oss.str().c_str());
6154           }
6155         }
6156     }
6157   updateTime();
6158 }
6159
6160 /*!
6161  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6162  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6163  * according to which the first facet of the cell should be oriented to have the normal vector
6164  * pointing out of cell.
6165  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6166  *         cells. The caller is to delete this array using decrRef() as it is no more
6167  *         needed. 
6168  *  \throw If \a this->getMeshDimension() != 3.
6169  *  \throw If \a this->getSpaceDimension() != 3.
6170  *  \throw If the coordinates array is not set.
6171  *  \throw If the nodal connectivity of cells is not defined.
6172  *
6173  *  \if ENABLE_EXAMPLES
6174  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6175  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6176  *  \endif
6177  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6178  */
6179 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6180 {
6181   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6182   if(getMeshDimension()!=3)
6183     throw INTERP_KERNEL::Exception(msg);
6184   int spaceDim=getSpaceDimension();
6185   if(spaceDim!=3)
6186     throw INTERP_KERNEL::Exception(msg);
6187   //
6188   int nbOfCells=getNumberOfCells();
6189   int *conn=_nodal_connec->getPointer();
6190   const int *connI=_nodal_connec_index->getConstPointer();
6191   const double *coo=getCoords()->getConstPointer();
6192   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6193   for(int i=0;i<nbOfCells;i++)
6194     {
6195       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6196       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6197         {
6198           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6199             {
6200               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6201               cells->pushBackSilent(i);
6202             }
6203         }
6204     }
6205   return cells.retn();
6206 }
6207
6208 /*!
6209  * This method is a faster method to correct orientation of all 3D cells in \a this.
6210  * 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.
6211  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6212  * 
6213  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6214  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6215  */
6216 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6217 {
6218   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6219     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6220   int nbOfCells=getNumberOfCells();
6221   int *conn=_nodal_connec->getPointer();
6222   const int *connI=_nodal_connec_index->getConstPointer();
6223   const double *coordsPtr=_coords->getConstPointer();
6224   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6225   for(int i=0;i<nbOfCells;i++)
6226     {
6227       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6228       switch(type)
6229       {
6230         case INTERP_KERNEL::NORM_TETRA4:
6231           {
6232             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6233               {
6234                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6235                 ret->pushBackSilent(i);
6236               }
6237             break;
6238           }
6239         case INTERP_KERNEL::NORM_PYRA5:
6240           {
6241             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6242               {
6243                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6244                 ret->pushBackSilent(i);
6245               }
6246             break;
6247           }
6248         case INTERP_KERNEL::NORM_PENTA6:
6249         case INTERP_KERNEL::NORM_HEXA8:
6250         case INTERP_KERNEL::NORM_HEXGP12:
6251           {
6252             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6253               {
6254                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6255                 ret->pushBackSilent(i);
6256               }
6257             break;
6258           }
6259         case INTERP_KERNEL::NORM_POLYHED:
6260           {
6261             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6262               {
6263                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6264                 ret->pushBackSilent(i);
6265               }
6266             break;
6267           }
6268         default:
6269           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 !");
6270       }
6271     }
6272   updateTime();
6273   return ret.retn();
6274 }
6275
6276 /*!
6277  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6278  * If it is not the case an exception will be thrown.
6279  * This method is fast because the first cell of \a this is used to compute the plane.
6280  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6281  * \param pos output of size at least 3 used to store a point owned of searched plane.
6282  */
6283 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6284 {
6285   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6286     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6287   const int *conn=_nodal_connec->getConstPointer();
6288   const int *connI=_nodal_connec_index->getConstPointer();
6289   const double *coordsPtr=_coords->getConstPointer();
6290   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6291   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6292 }
6293
6294 /*!
6295  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6296  * cells. Currently cells of the following types are treated:
6297  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6298  * For a cell of other type an exception is thrown.
6299  * Space dimension of a 2D mesh can be either 2 or 3.
6300  * The Edge Ratio of a cell \f$t\f$ is: 
6301  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6302  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6303  *  the smallest edge lengths of \f$t\f$.
6304  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6305  *          cells and one time, lying on \a this mesh. The caller is to delete this
6306  *          field using decrRef() as it is no more needed. 
6307  *  \throw If the coordinates array is not set.
6308  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6309  *  \throw If the connectivity data array has more than one component.
6310  *  \throw If the connectivity data array has a named component.
6311  *  \throw If the connectivity index data array has more than one component.
6312  *  \throw If the connectivity index data array has a named component.
6313  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6314  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6315  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6316  */
6317 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6318 {
6319   checkCoherency();
6320   int spaceDim=getSpaceDimension();
6321   int meshDim=getMeshDimension();
6322   if(spaceDim!=2 && spaceDim!=3)
6323     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6324   if(meshDim!=2 && meshDim!=3)
6325     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6326   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6327   ret->setMesh(this);
6328   int nbOfCells=getNumberOfCells();
6329   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6330   arr->alloc(nbOfCells,1);
6331   double *pt=arr->getPointer();
6332   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6333   const int *conn=_nodal_connec->getConstPointer();
6334   const int *connI=_nodal_connec_index->getConstPointer();
6335   const double *coo=_coords->getConstPointer();
6336   double tmp[12];
6337   for(int i=0;i<nbOfCells;i++,pt++)
6338     {
6339       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6340       switch(t)
6341       {
6342         case INTERP_KERNEL::NORM_TRI3:
6343           {
6344             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6345             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6346             break;
6347           }
6348         case INTERP_KERNEL::NORM_QUAD4:
6349           {
6350             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6351             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6352             break;
6353           }
6354         case INTERP_KERNEL::NORM_TETRA4:
6355           {
6356             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6357             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6358             break;
6359           }
6360         default:
6361           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6362       }
6363       conn+=connI[i+1]-connI[i];
6364     }
6365   ret->setName("EdgeRatio");
6366   ret->synchronizeTimeWithSupport();
6367   return ret.retn();
6368 }
6369
6370 /*!
6371  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6372  * cells. Currently cells of the following types are treated:
6373  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6374  * For a cell of other type an exception is thrown.
6375  * Space dimension of a 2D mesh can be either 2 or 3.
6376  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6377  *          cells and one time, lying on \a this mesh. The caller is to delete this
6378  *          field using decrRef() as it is no more needed. 
6379  *  \throw If the coordinates array is not set.
6380  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6381  *  \throw If the connectivity data array has more than one component.
6382  *  \throw If the connectivity data array has a named component.
6383  *  \throw If the connectivity index data array has more than one component.
6384  *  \throw If the connectivity index data array has a named component.
6385  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6386  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6387  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6388  */
6389 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6390 {
6391   checkCoherency();
6392   int spaceDim=getSpaceDimension();
6393   int meshDim=getMeshDimension();
6394   if(spaceDim!=2 && spaceDim!=3)
6395     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6396   if(meshDim!=2 && meshDim!=3)
6397     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6398   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6399   ret->setMesh(this);
6400   int nbOfCells=getNumberOfCells();
6401   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6402   arr->alloc(nbOfCells,1);
6403   double *pt=arr->getPointer();
6404   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6405   const int *conn=_nodal_connec->getConstPointer();
6406   const int *connI=_nodal_connec_index->getConstPointer();
6407   const double *coo=_coords->getConstPointer();
6408   double tmp[12];
6409   for(int i=0;i<nbOfCells;i++,pt++)
6410     {
6411       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6412       switch(t)
6413       {
6414         case INTERP_KERNEL::NORM_TRI3:
6415           {
6416             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6417             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6418             break;
6419           }
6420         case INTERP_KERNEL::NORM_QUAD4:
6421           {
6422             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6423             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6424             break;
6425           }
6426         case INTERP_KERNEL::NORM_TETRA4:
6427           {
6428             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6429             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6430             break;
6431           }
6432         default:
6433           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6434       }
6435       conn+=connI[i+1]-connI[i];
6436     }
6437   ret->setName("AspectRatio");
6438   ret->synchronizeTimeWithSupport();
6439   return ret.retn();
6440 }
6441
6442 /*!
6443  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6444  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6445  * treated: INTERP_KERNEL::NORM_QUAD4.
6446  * For a cell of other type an exception is thrown.
6447  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6448  *          cells and one time, lying on \a this mesh. The caller is to delete this
6449  *          field using decrRef() as it is no more needed. 
6450  *  \throw If the coordinates array is not set.
6451  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6452  *  \throw If the connectivity data array has more than one component.
6453  *  \throw If the connectivity data array has a named component.
6454  *  \throw If the connectivity index data array has more than one component.
6455  *  \throw If the connectivity index data array has a named component.
6456  *  \throw If \a this->getMeshDimension() != 2.
6457  *  \throw If \a this->getSpaceDimension() != 3.
6458  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6459  */
6460 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6461 {
6462   checkCoherency();
6463   int spaceDim=getSpaceDimension();
6464   int meshDim=getMeshDimension();
6465   if(spaceDim!=3)
6466     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6467   if(meshDim!=2)
6468     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6469   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6470   ret->setMesh(this);
6471   int nbOfCells=getNumberOfCells();
6472   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6473   arr->alloc(nbOfCells,1);
6474   double *pt=arr->getPointer();
6475   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6476   const int *conn=_nodal_connec->getConstPointer();
6477   const int *connI=_nodal_connec_index->getConstPointer();
6478   const double *coo=_coords->getConstPointer();
6479   double tmp[12];
6480   for(int i=0;i<nbOfCells;i++,pt++)
6481     {
6482       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6483       switch(t)
6484       {
6485         case INTERP_KERNEL::NORM_QUAD4:
6486           {
6487             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6488             *pt=INTERP_KERNEL::quadWarp(tmp);
6489             break;
6490           }
6491         default:
6492           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6493       }
6494       conn+=connI[i+1]-connI[i];
6495     }
6496   ret->setName("Warp");
6497   ret->synchronizeTimeWithSupport();
6498   return ret.retn();
6499 }
6500
6501
6502 /*!
6503  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6504  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6505  * treated: INTERP_KERNEL::NORM_QUAD4.
6506  * For a cell of other type an exception is thrown.
6507  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6508  *          cells and one time, lying on \a this mesh. The caller is to delete this
6509  *          field using decrRef() as it is no more needed. 
6510  *  \throw If the coordinates array is not set.
6511  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6512  *  \throw If the connectivity data array has more than one component.
6513  *  \throw If the connectivity data array has a named component.
6514  *  \throw If the connectivity index data array has more than one component.
6515  *  \throw If the connectivity index data array has a named component.
6516  *  \throw If \a this->getMeshDimension() != 2.
6517  *  \throw If \a this->getSpaceDimension() != 3.
6518  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6519  */
6520 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6521 {
6522   checkCoherency();
6523   int spaceDim=getSpaceDimension();
6524   int meshDim=getMeshDimension();
6525   if(spaceDim!=3)
6526     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6527   if(meshDim!=2)
6528     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6529   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6530   ret->setMesh(this);
6531   int nbOfCells=getNumberOfCells();
6532   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6533   arr->alloc(nbOfCells,1);
6534   double *pt=arr->getPointer();
6535   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6536   const int *conn=_nodal_connec->getConstPointer();
6537   const int *connI=_nodal_connec_index->getConstPointer();
6538   const double *coo=_coords->getConstPointer();
6539   double tmp[12];
6540   for(int i=0;i<nbOfCells;i++,pt++)
6541     {
6542       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6543       switch(t)
6544       {
6545         case INTERP_KERNEL::NORM_QUAD4:
6546           {
6547             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6548             *pt=INTERP_KERNEL::quadSkew(tmp);
6549             break;
6550           }
6551         default:
6552           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6553       }
6554       conn+=connI[i+1]-connI[i];
6555     }
6556   ret->setName("Skew");
6557   ret->synchronizeTimeWithSupport();
6558   return ret.retn();
6559 }
6560
6561 /*!
6562  * 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.
6563  *
6564  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6565  *
6566  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6567  */
6568 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6569 {
6570   checkCoherency();
6571   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6572   ret->setMesh(this);
6573   std::set<INTERP_KERNEL::NormalizedCellType> types;
6574   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6575   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6576   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6577   arr->alloc(nbCells,1);
6578   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6579     {
6580       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6581       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6582       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6583     }
6584   ret->setArray(arr);
6585   ret->setName("Diameter");
6586   return ret.retn();
6587 }
6588
6589 /*!
6590  * This method aggregate the bbox of each cell and put it into bbox parameter.
6591  * 
6592  * \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)
6593  *                         For all other cases this input parameter is ignored.
6594  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6595  * 
6596  * \throw If \a this is not fully set (coordinates and connectivity).
6597  * \throw If a cell in \a this has no valid nodeId.
6598  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6599  */
6600 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6601 {
6602   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6603   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.
6604     return getBoundingBoxForBBTreeFast();
6605   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6606     {
6607       bool presenceOfQuadratic(false);
6608       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6609         {
6610           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6611           if(cm.isQuadratic())
6612             presenceOfQuadratic=true;
6613         }
6614       if(!presenceOfQuadratic)
6615         return getBoundingBoxForBBTreeFast();
6616       if(mDim==2 && sDim==2)
6617         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6618       else
6619         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6620     }
6621   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) !");
6622 }
6623
6624 /*!
6625  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6626  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6627  * 
6628  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6629  * 
6630  * \throw If \a this is not fully set (coordinates and connectivity).
6631  * \throw If a cell in \a this has no valid nodeId.
6632  */
6633 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6634 {
6635   checkFullyDefined();
6636   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6637   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6638   double *bbox(ret->getPointer());
6639   for(int i=0;i<nbOfCells*spaceDim;i++)
6640     {
6641       bbox[2*i]=std::numeric_limits<double>::max();
6642       bbox[2*i+1]=-std::numeric_limits<double>::max();
6643     }
6644   const double *coordsPtr(_coords->getConstPointer());
6645   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6646   for(int i=0;i<nbOfCells;i++)
6647     {
6648       int offset=connI[i]+1;
6649       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6650       for(int j=0;j<nbOfNodesForCell;j++)
6651         {
6652           int nodeId=conn[offset+j];
6653           if(nodeId>=0 && nodeId<nbOfNodes)
6654             {
6655               for(int k=0;k<spaceDim;k++)
6656                 {
6657                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6658                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6659                 }
6660               kk++;
6661             }
6662         }
6663       if(kk==0)
6664         {
6665           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6666           throw INTERP_KERNEL::Exception(oss.str().c_str());
6667         }
6668     }
6669   return ret.retn();
6670 }
6671
6672 /*!
6673  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6674  * useful for 2D meshes having quadratic cells
6675  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6676  * the two extremities of the arc of circle).
6677  * 
6678  * \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)
6679  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6680  * \throw If \a this is not fully defined.
6681  * \throw If \a this is not a mesh with meshDimension equal to 2.
6682  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6683  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6684  */
6685 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6686 {
6687   checkFullyDefined();
6688   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6689   if(spaceDim!=2 || mDim!=2)
6690     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!");
6691   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6692   double *bbox(ret->getPointer());
6693   const double *coords(_coords->getConstPointer());
6694   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6695   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6696     {
6697       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6698       int sz(connI[1]-connI[0]-1);
6699       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6700       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6701       INTERP_KERNEL::QuadraticPolygon *pol(0);
6702       for(int j=0;j<sz;j++)
6703         {
6704           int nodeId(conn[*connI+1+j]);
6705           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6706         }
6707       if(!cm.isQuadratic())
6708         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6709       else
6710         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6711       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6712       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6713     }
6714   return ret.retn();
6715 }
6716
6717 /*!
6718  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6719  * useful for 2D meshes having quadratic cells
6720  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6721  * the two extremities of the arc of circle).
6722  * 
6723  * \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)
6724  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6725  * \throw If \a this is not fully defined.
6726  * \throw If \a this is not a mesh with meshDimension equal to 1.
6727  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6728  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6729  */
6730 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6731 {
6732   checkFullyDefined();
6733   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6734   if(spaceDim!=2 || mDim!=1)
6735     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!");
6736   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6737   double *bbox(ret->getPointer());
6738   const double *coords(_coords->getConstPointer());
6739   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6740   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6741     {
6742       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6743       int sz(connI[1]-connI[0]-1);
6744       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6745       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6746       INTERP_KERNEL::Edge *edge(0);
6747       for(int j=0;j<sz;j++)
6748         {
6749           int nodeId(conn[*connI+1+j]);
6750           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6751         }
6752       if(!cm.isQuadratic())
6753         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6754       else
6755         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6756       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6757       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6758     }
6759   return ret.retn();
6760 }
6761
6762 /// @cond INTERNAL
6763
6764 namespace ParaMEDMEMImpl
6765 {
6766   class ConnReader
6767   {
6768   public:
6769     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6770     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6771   private:
6772     const int *_conn;
6773     int _val;
6774   };
6775
6776   class ConnReader2
6777   {
6778   public:
6779     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6780     bool operator() (const int& pos) { return _conn[pos]==_val; }
6781   private:
6782     const int *_conn;
6783     int _val;
6784   };
6785 }
6786
6787 /// @endcond
6788
6789 /*!
6790  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6791  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6792  * \a this is composed in cell types.
6793  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6794  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6795  * This parameter is kept only for compatibility with other methode listed above.
6796  */
6797 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6798 {
6799   checkConnectivityFullyDefined();
6800   const int *conn=_nodal_connec->getConstPointer();
6801   const int *connI=_nodal_connec_index->getConstPointer();
6802   const int *work=connI;
6803   int nbOfCells=getNumberOfCells();
6804   std::size_t n=getAllGeoTypes().size();
6805   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6806   std::set<INTERP_KERNEL::NormalizedCellType> types;
6807   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6808     {
6809       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6810       if(types.find(typ)!=types.end())
6811         {
6812           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6813           oss << " is not contiguous !";
6814           throw INTERP_KERNEL::Exception(oss.str().c_str());
6815         }
6816       types.insert(typ);
6817       ret[3*i]=typ;
6818       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6819       ret[3*i+1]=(int)std::distance(work,work2);
6820       work=work2;
6821     }
6822   return ret;
6823 }
6824
6825 /*!
6826  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6827  * only for types cell, type node is not managed.
6828  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6829  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6830  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6831  * If 2 or more same geometric type is in \a code and exception is thrown too.
6832  *
6833  * This method firstly checks
6834  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6835  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6836  * an exception is thrown too.
6837  * 
6838  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6839  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6840  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6841  */
6842 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6843 {
6844   if(code.empty())
6845     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6846   std::size_t sz=code.size();
6847   std::size_t n=sz/3;
6848   if(sz%3!=0)
6849     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6850   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6851   int nb=0;
6852   bool isNoPflUsed=true;
6853   for(std::size_t i=0;i<n;i++)
6854     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6855       {
6856         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6857         nb+=code[3*i+1];
6858         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6859           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6860         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6861       }
6862   if(types.size()!=n)
6863     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6864   if(isNoPflUsed)
6865     {
6866       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6867         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6868       if(types.size()==_types.size())
6869         return 0;
6870     }
6871   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6872   ret->alloc(nb,1);
6873   int *retPtr=ret->getPointer();
6874   const int *connI=_nodal_connec_index->getConstPointer();
6875   const int *conn=_nodal_connec->getConstPointer();
6876   int nbOfCells=getNumberOfCells();
6877   const int *i=connI;
6878   int kk=0;
6879   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6880     {
6881       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6882       int offset=(int)std::distance(connI,i);
6883       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6884       int nbOfCellsOfCurType=(int)std::distance(i,j);
6885       if(code[3*kk+2]==-1)
6886         for(int k=0;k<nbOfCellsOfCurType;k++)
6887           *retPtr++=k+offset;
6888       else
6889         {
6890           int idInIdsPerType=code[3*kk+2];
6891           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6892             {
6893               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6894               if(zePfl)
6895                 {
6896                   zePfl->checkAllocated();
6897                   if(zePfl->getNumberOfComponents()==1)
6898                     {
6899                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6900                         {
6901                           if(*k>=0 && *k<nbOfCellsOfCurType)
6902                             *retPtr=(*k)+offset;
6903                           else
6904                             {
6905                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6906                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6907                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6908                             }
6909                         }
6910                     }
6911                   else
6912                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6913                 }
6914               else
6915                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6916             }
6917           else
6918             {
6919               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6920               oss << " should be in [0," << idsPerType.size() << ") !";
6921               throw INTERP_KERNEL::Exception(oss.str().c_str());
6922             }
6923         }
6924       i=j;
6925     }
6926   return ret.retn();
6927 }
6928
6929 /*!
6930  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6931  * 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.
6932  * 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.
6933  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6934  * 
6935  * \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.
6936  * \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,
6937  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6938  * \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.
6939  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6940  * \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
6941  */
6942 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6943 {
6944   if(!profile)
6945     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6946   if(profile->getNumberOfComponents()!=1)
6947     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6948   checkConnectivityFullyDefined();
6949   const int *conn=_nodal_connec->getConstPointer();
6950   const int *connI=_nodal_connec_index->getConstPointer();
6951   int nbOfCells=getNumberOfCells();
6952   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6953   std::vector<int> typeRangeVals(1);
6954   for(const int *i=connI;i!=connI+nbOfCells;)
6955     {
6956       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6957       if(std::find(types.begin(),types.end(),curType)!=types.end())
6958         {
6959           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6960         }
6961       types.push_back(curType);
6962       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6963       typeRangeVals.push_back((int)std::distance(connI,i));
6964     }
6965   //
6966   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6967   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6968   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6969   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6970   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6971   //
6972   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6973   code.resize(3*nbOfCastsFinal);
6974   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6975   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6976   for(int i=0;i<nbOfCastsFinal;i++)
6977     {
6978       int castId=castsPresent->getIJ(i,0);
6979       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6980       idsInPflPerType2.push_back(tmp3);
6981       code[3*i]=(int)types[castId];
6982       code[3*i+1]=tmp3->getNumberOfTuples();
6983       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6984       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6985         {
6986           tmp4->copyStringInfoFrom(*profile);
6987           idsPerType2.push_back(tmp4);
6988           code[3*i+2]=(int)idsPerType2.size()-1;
6989         }
6990       else
6991         {
6992           code[3*i+2]=-1;
6993         }
6994     }
6995   std::size_t sz2=idsInPflPerType2.size();
6996   idsInPflPerType.resize(sz2);
6997   for(std::size_t i=0;i<sz2;i++)
6998     {
6999       DataArrayInt *locDa=idsInPflPerType2[i];
7000       locDa->incrRef();
7001       idsInPflPerType[i]=locDa;
7002     }
7003   std::size_t sz=idsPerType2.size();
7004   idsPerType.resize(sz);
7005   for(std::size_t i=0;i<sz;i++)
7006     {
7007       DataArrayInt *locDa=idsPerType2[i];
7008       locDa->incrRef();
7009       idsPerType[i]=locDa;
7010     }
7011 }
7012
7013 /*!
7014  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
7015  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
7016  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
7017  * 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.
7018  */
7019 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
7020 {
7021   checkFullyDefined();
7022   nM1LevMesh->checkFullyDefined();
7023   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
7024     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
7025   if(_coords!=nM1LevMesh->getCoords())
7026     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
7027   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
7028   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
7029   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
7030   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
7031   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
7032   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
7033   tmp->setConnectivity(tmp0,tmp1);
7034   tmp->renumberCells(ret0->getConstPointer(),false);
7035   revDesc=tmp->getNodalConnectivity();
7036   revDescIndx=tmp->getNodalConnectivityIndex();
7037   DataArrayInt *ret=0;
7038   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7039     {
7040       int tmp2;
7041       ret->getMaxValue(tmp2);
7042       ret->decrRef();
7043       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7044       throw INTERP_KERNEL::Exception(oss.str().c_str());
7045     }
7046   nM1LevMeshIds=ret;
7047   //
7048   revDesc->incrRef();
7049   revDescIndx->incrRef();
7050   ret1->incrRef();
7051   ret0->incrRef();
7052   meshnM1Old2New=ret0;
7053   return ret1;
7054 }
7055
7056 /*!
7057  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7058  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7059  * in "Old to New" mode.
7060  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7061  *          this array using decrRef() as it is no more needed.
7062  *  \throw If the nodal connectivity of cells is not defined.
7063  */
7064 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7065 {
7066   checkConnectivityFullyDefined();
7067   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7068   renumberCells(ret->getConstPointer(),false);
7069   return ret.retn();
7070 }
7071
7072 /*!
7073  * This methods checks that cells are sorted by their types.
7074  * This method makes asumption (no check) that connectivity is correctly set before calling.
7075  */
7076 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7077 {
7078   checkFullyDefined();
7079   const int *conn=_nodal_connec->getConstPointer();
7080   const int *connI=_nodal_connec_index->getConstPointer();
7081   int nbOfCells=getNumberOfCells();
7082   std::set<INTERP_KERNEL::NormalizedCellType> types;
7083   for(const int *i=connI;i!=connI+nbOfCells;)
7084     {
7085       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7086       if(types.find(curType)!=types.end())
7087         return false;
7088       types.insert(curType);
7089       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7090     }
7091   return true;
7092 }
7093
7094 /*!
7095  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7096  * The geometric type order is specified by MED file.
7097  * 
7098  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7099  */
7100 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7101 {
7102   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7103 }
7104
7105 /*!
7106  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7107  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7108  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7109  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7110  */
7111 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7112 {
7113   checkFullyDefined();
7114   const int *conn=_nodal_connec->getConstPointer();
7115   const int *connI=_nodal_connec_index->getConstPointer();
7116   int nbOfCells=getNumberOfCells();
7117   if(nbOfCells==0)
7118     return true;
7119   int lastPos=-1;
7120   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7121   for(const int *i=connI;i!=connI+nbOfCells;)
7122     {
7123       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7124       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7125       if(isTypeExists!=orderEnd)
7126         {
7127           int pos=(int)std::distance(orderBg,isTypeExists);
7128           if(pos<=lastPos)
7129             return false;
7130           lastPos=pos;
7131           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7132         }
7133       else
7134         {
7135           if(sg.find(curType)==sg.end())
7136             {
7137               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7138               sg.insert(curType);
7139             }
7140           else
7141             return false;
7142         }
7143     }
7144   return true;
7145 }
7146
7147 /*!
7148  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7149  * 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
7150  * 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'.
7151  */
7152 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7153 {
7154   checkConnectivityFullyDefined();
7155   int nbOfCells=getNumberOfCells();
7156   const int *conn=_nodal_connec->getConstPointer();
7157   const int *connI=_nodal_connec_index->getConstPointer();
7158   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7159   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7160   tmpa->alloc(nbOfCells,1);
7161   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7162   tmpb->fillWithZero();
7163   int *tmp=tmpa->getPointer();
7164   int *tmp2=tmpb->getPointer();
7165   for(const int *i=connI;i!=connI+nbOfCells;i++)
7166     {
7167       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7168       if(where!=orderEnd)
7169         {
7170           int pos=(int)std::distance(orderBg,where);
7171           tmp2[pos]++;
7172           tmp[std::distance(connI,i)]=pos;
7173         }
7174       else
7175         {
7176           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7177           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7178           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7179           throw INTERP_KERNEL::Exception(oss.str().c_str());
7180         }
7181     }
7182   nbPerType=tmpb.retn();
7183   return tmpa.retn();
7184 }
7185
7186 /*!
7187  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7188  *
7189  * \return a new object containing the old to new correspondance.
7190  *
7191  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7192  */
7193 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7194 {
7195   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7196 }
7197
7198 /*!
7199  * 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.
7200  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7201  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7202  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7203  */
7204 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7205 {
7206   DataArrayInt *nbPerType=0;
7207   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7208   nbPerType->decrRef();
7209   return tmpa->buildPermArrPerLevel();
7210 }
7211
7212 /*!
7213  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7214  * The number of cells remains unchanged after the call of this method.
7215  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7216  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7217  *
7218  * \return the array giving the correspondance old to new.
7219  */
7220 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7221 {
7222   checkFullyDefined();
7223   computeTypes();
7224   const int *conn=_nodal_connec->getConstPointer();
7225   const int *connI=_nodal_connec_index->getConstPointer();
7226   int nbOfCells=getNumberOfCells();
7227   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7228   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7229     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7230       {
7231         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7232         types.push_back(curType);
7233         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7234       }
7235   DataArrayInt *ret=DataArrayInt::New();
7236   ret->alloc(nbOfCells,1);
7237   int *retPtr=ret->getPointer();
7238   std::fill(retPtr,retPtr+nbOfCells,-1);
7239   int newCellId=0;
7240   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7241     {
7242       for(const int *i=connI;i!=connI+nbOfCells;i++)
7243         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7244           retPtr[std::distance(connI,i)]=newCellId++;
7245     }
7246   renumberCells(retPtr,false);
7247   return ret;
7248 }
7249
7250 /*!
7251  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7252  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7253  * This method makes asumption that connectivity is correctly set before calling.
7254  */
7255 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7256 {
7257   checkConnectivityFullyDefined();
7258   const int *conn=_nodal_connec->getConstPointer();
7259   const int *connI=_nodal_connec_index->getConstPointer();
7260   int nbOfCells=getNumberOfCells();
7261   std::vector<MEDCouplingUMesh *> ret;
7262   for(const int *i=connI;i!=connI+nbOfCells;)
7263     {
7264       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7265       int beginCellId=(int)std::distance(connI,i);
7266       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7267       int endCellId=(int)std::distance(connI,i);
7268       int sz=endCellId-beginCellId;
7269       int *cells=new int[sz];
7270       for(int j=0;j<sz;j++)
7271         cells[j]=beginCellId+j;
7272       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7273       delete [] cells;
7274       ret.push_back(m);
7275     }
7276   return ret;
7277 }
7278
7279 /*!
7280  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7281  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7282  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7283  *
7284  * \return a newly allocated instance, that the caller must manage.
7285  * \throw If \a this contains more than one geometric type.
7286  * \throw If the nodal connectivity of \a this is not fully defined.
7287  * \throw If the internal data is not coherent.
7288  */
7289 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7290 {
7291   checkConnectivityFullyDefined();
7292   if(_types.size()!=1)
7293     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7294   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7295   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7296   ret->setCoords(getCoords());
7297   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7298   if(retC)
7299     {
7300       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7301       retC->setNodalConnectivity(c);
7302     }
7303   else
7304     {
7305       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7306       if(!retD)
7307         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7308       DataArrayInt *c=0,*ci=0;
7309       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7310       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7311       retD->setNodalConnectivity(cs,cis);
7312     }
7313   return ret.retn();
7314 }
7315
7316 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7317 {
7318   checkConnectivityFullyDefined();
7319   if(_types.size()!=1)
7320     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7321   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7322   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7323   if(cm.isDynamic())
7324     {
7325       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7326       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7327       throw INTERP_KERNEL::Exception(oss.str().c_str());
7328     }
7329   int nbCells=getNumberOfCells();
7330   int typi=(int)typ;
7331   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7332   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7333   int *outPtr=connOut->getPointer();
7334   const int *conn=_nodal_connec->begin();
7335   const int *connI=_nodal_connec_index->begin();
7336   nbNodesPerCell++;
7337   for(int i=0;i<nbCells;i++,connI++)
7338     {
7339       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7340         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7341       else
7342         {
7343           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 << ") !";
7344           throw INTERP_KERNEL::Exception(oss.str().c_str());
7345         }
7346     }
7347   return connOut.retn();
7348 }
7349
7350 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7351 {
7352   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7353   checkConnectivityFullyDefined();
7354   if(_types.size()!=1)
7355     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7356   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7357   if(lgth<nbCells)
7358     throw INTERP_KERNEL::Exception(msg0);
7359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7360   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7361   int *cp(c->getPointer()),*cip(ci->getPointer());
7362   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7363   cip[0]=0;
7364   for(int i=0;i<nbCells;i++,cip++,incip++)
7365     {
7366       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7367       int delta(stop-strt);
7368       if(delta>=1)
7369         {
7370           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7371             cp=std::copy(incp+strt,incp+stop,cp);
7372           else
7373             throw INTERP_KERNEL::Exception(msg0);
7374         }
7375       else
7376         throw INTERP_KERNEL::Exception(msg0);
7377       cip[1]=cip[0]+delta;
7378     }
7379   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7380 }
7381
7382 /*!
7383  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7384  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7385  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7386  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7387  * are not used here to avoid the build of big permutation array.
7388  *
7389  * \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
7390  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7391  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7392  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7393  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7394  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7395  * \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
7396  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7397  */
7398 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7399                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7400                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7401 {
7402   std::vector<const MEDCouplingUMesh *> ms2;
7403   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7404     if(*it)
7405       {
7406         (*it)->checkConnectivityFullyDefined();
7407         ms2.push_back(*it);
7408       }
7409   if(ms2.empty())
7410     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7411   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7412   int meshDim=ms2[0]->getMeshDimension();
7413   std::vector<const MEDCouplingUMesh *> m1ssm;
7414   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7415   //
7416   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7417   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7418   int fake=0,rk=0;
7419   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7420   ret1->alloc(0,1); ret2->alloc(0,1);
7421   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7422     {
7423       if(meshDim!=(*it)->getMeshDimension())
7424         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7425       if(refCoo!=(*it)->getCoords())
7426         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7427       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7428       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7429       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7430       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7431         {
7432           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7433           m1ssmSingleAuto.push_back(singleCell);
7434           m1ssmSingle.push_back(singleCell);
7435           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7436         }
7437     }
7438   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7439   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7440   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7441   for(std::size_t i=0;i<m1ssm.size();i++)
7442     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7443   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7444   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7445   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7446   return ret0.retn();
7447 }
7448
7449 /*!
7450  * This method returns a newly created DataArrayInt instance.
7451  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7452  */
7453 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7454 {
7455   checkFullyDefined();
7456   const int *conn=_nodal_connec->getConstPointer();
7457   const int *connIndex=_nodal_connec_index->getConstPointer();
7458   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7459   for(const int *w=begin;w!=end;w++)
7460     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7461       ret->pushBackSilent(*w);
7462   return ret.retn();
7463 }
7464
7465 /*!
7466  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7467  * are in [0:getNumberOfCells())
7468  */
7469 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7470 {
7471   checkFullyDefined();
7472   const int *conn=_nodal_connec->getConstPointer();
7473   const int *connI=_nodal_connec_index->getConstPointer();
7474   int nbOfCells=getNumberOfCells();
7475   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7476   int *tmp=new int[nbOfCells];
7477   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7478     {
7479       int j=0;
7480       for(const int *i=connI;i!=connI+nbOfCells;i++)
7481         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7482           tmp[std::distance(connI,i)]=j++;
7483     }
7484   DataArrayInt *ret=DataArrayInt::New();
7485   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7486   ret->copyStringInfoFrom(*da);
7487   int *retPtr=ret->getPointer();
7488   const int *daPtr=da->getConstPointer();
7489   int nbOfElems=da->getNbOfElems();
7490   for(int k=0;k<nbOfElems;k++)
7491     retPtr[k]=tmp[daPtr[k]];
7492   delete [] tmp;
7493   return ret;
7494 }
7495
7496 /*!
7497  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7498  * This method \b works \b for mesh sorted by type.
7499  * cells whose ids is in 'idsPerGeoType' array.
7500  * This method conserves coords and name of mesh.
7501  */
7502 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7503 {
7504   std::vector<int> code=getDistributionOfTypes();
7505   std::size_t nOfTypesInThis=code.size()/3;
7506   int sz=0,szOfType=0;
7507   for(std::size_t i=0;i<nOfTypesInThis;i++)
7508     {
7509       if(code[3*i]!=type)
7510         sz+=code[3*i+1];
7511       else
7512         szOfType=code[3*i+1];
7513     }
7514   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7515     if(*work<0 || *work>=szOfType)
7516       {
7517         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7518         oss << ". It should be in [0," << szOfType << ") !";
7519         throw INTERP_KERNEL::Exception(oss.str().c_str());
7520       }
7521   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7522   int *idsPtr=idsTokeep->getPointer();
7523   int offset=0;
7524   for(std::size_t i=0;i<nOfTypesInThis;i++)
7525     {
7526       if(code[3*i]!=type)
7527         for(int j=0;j<code[3*i+1];j++)
7528           *idsPtr++=offset+j;
7529       else
7530         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7531       offset+=code[3*i+1];
7532     }
7533   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7534   ret->copyTinyInfoFrom(this);
7535   return ret.retn();
7536 }
7537
7538 /*!
7539  * This method returns a vector of size 'this->getNumberOfCells()'.
7540  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7541  */
7542 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7543 {
7544   int ncell=getNumberOfCells();
7545   std::vector<bool> ret(ncell);
7546   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7547   const int *c=getNodalConnectivity()->getConstPointer();
7548   for(int i=0;i<ncell;i++)
7549     {
7550       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7551       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7552       ret[i]=cm.isQuadratic();
7553     }
7554   return ret;
7555 }
7556
7557 /*!
7558  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7559  */
7560 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7561 {
7562   if(other->getType()!=UNSTRUCTURED)
7563     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7564   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7565   return MergeUMeshes(this,otherC);
7566 }
7567
7568 /*!
7569  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7570  * computed by averaging coordinates of cell nodes, so this method is not a right
7571  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7572  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7573  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7574  *          components. The caller is to delete this array using decrRef() as it is
7575  *          no more needed.
7576  *  \throw If the coordinates array is not set.
7577  *  \throw If the nodal connectivity of cells is not defined.
7578  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7579  */
7580 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7581 {
7582   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7583   int spaceDim=getSpaceDimension();
7584   int nbOfCells=getNumberOfCells();
7585   ret->alloc(nbOfCells,spaceDim);
7586   ret->copyStringInfoFrom(*getCoords());
7587   double *ptToFill=ret->getPointer();
7588   const int *nodal=_nodal_connec->getConstPointer();
7589   const int *nodalI=_nodal_connec_index->getConstPointer();
7590   const double *coor=_coords->getConstPointer();
7591   for(int i=0;i<nbOfCells;i++)
7592     {
7593       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7594       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7595       ptToFill+=spaceDim;
7596     }
7597   return ret.retn();
7598 }
7599
7600 /*!
7601  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7602  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7603  * 
7604  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7605  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7606  * 
7607  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7608  * \throw If \a this is not fully defined (coordinates and connectivity)
7609  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7610  */
7611 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7612 {
7613   checkFullyDefined();
7614   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7615   int spaceDim=getSpaceDimension();
7616   int nbOfCells=getNumberOfCells();
7617   int nbOfNodes=getNumberOfNodes();
7618   ret->alloc(nbOfCells,spaceDim);
7619   double *ptToFill=ret->getPointer();
7620   const int *nodal=_nodal_connec->getConstPointer();
7621   const int *nodalI=_nodal_connec_index->getConstPointer();
7622   const double *coor=_coords->getConstPointer();
7623   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7624     {
7625       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7626       std::fill(ptToFill,ptToFill+spaceDim,0.);
7627       if(type!=INTERP_KERNEL::NORM_POLYHED)
7628         {
7629           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7630             {
7631               if(*conn>=0 && *conn<nbOfNodes)
7632                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7633               else
7634                 {
7635                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7636                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7637                 }
7638             }
7639           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7640           if(nbOfNodesInCell>0)
7641             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7642           else
7643             {
7644               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7645               throw INTERP_KERNEL::Exception(oss.str().c_str());
7646             }
7647         }
7648       else
7649         {
7650           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7651           s.erase(-1);
7652           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7653             {
7654               if(*it>=0 && *it<nbOfNodes)
7655                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7656               else
7657                 {
7658                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7659                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7660                 }
7661             }
7662           if(!s.empty())
7663             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7664           else
7665             {
7666               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7667               throw INTERP_KERNEL::Exception(oss.str().c_str());
7668             }
7669         }
7670     }
7671   return ret.retn();
7672 }
7673
7674 /*!
7675  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7676  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7677  * are specified via an array of cell ids. 
7678  *  \warning Validity of the specified cell ids is not checked! 
7679  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7680  *  \param [in] begin - an array of cell ids of interest.
7681  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7682  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7683  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7684  *          caller is to delete this array using decrRef() as it is no more needed. 
7685  *  \throw If the coordinates array is not set.
7686  *  \throw If the nodal connectivity of cells is not defined.
7687  *
7688  *  \if ENABLE_EXAMPLES
7689  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7690  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7691  *  \endif
7692  */
7693 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7694 {
7695   DataArrayDouble *ret=DataArrayDouble::New();
7696   int spaceDim=getSpaceDimension();
7697   int nbOfTuple=(int)std::distance(begin,end);
7698   ret->alloc(nbOfTuple,spaceDim);
7699   double *ptToFill=ret->getPointer();
7700   double *tmp=new double[spaceDim];
7701   const int *nodal=_nodal_connec->getConstPointer();
7702   const int *nodalI=_nodal_connec_index->getConstPointer();
7703   const double *coor=_coords->getConstPointer();
7704   for(const int *w=begin;w!=end;w++)
7705     {
7706       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7707       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7708       ptToFill+=spaceDim;
7709     }
7710   delete [] tmp;
7711   return ret;
7712 }
7713
7714 /*!
7715  * 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".
7716  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7717  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7718  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7719  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7720  * 
7721  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7722  * \throw If spaceDim!=3 or meshDim!=2.
7723  * \throw If connectivity of \a this is invalid.
7724  * \throw If connectivity of a cell in \a this points to an invalid node.
7725  */
7726 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7727 {
7728   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7729   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7730   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7731     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7732   ret->alloc(nbOfCells,4);
7733   double *retPtr(ret->getPointer());
7734   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7735   const double *coor(_coords->begin());
7736   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7737     {
7738       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7739       if(nodalI[1]-nodalI[0]>=3)
7740         {
7741           for(int j=0;j<3;j++)
7742             {
7743               int nodeId(nodal[nodalI[0]+1+j]);
7744               if(nodeId>=0 && nodeId<nbOfNodes)
7745                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7746               else
7747                 {
7748                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7749                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7750                 }
7751             }
7752         }
7753       else
7754         {
7755           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7756           throw INTERP_KERNEL::Exception(oss.str().c_str());
7757         }
7758       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7759       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7760     }
7761   return ret.retn();
7762 }
7763
7764 /*!
7765  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7766  * 
7767  */
7768 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7769 {
7770   if(!da)
7771     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7772   da->checkAllocated();
7773   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7774   ret->setCoords(da);
7775   int nbOfTuples=da->getNumberOfTuples();
7776   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7777   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7778   c->alloc(2*nbOfTuples,1);
7779   cI->alloc(nbOfTuples+1,1);
7780   int *cp=c->getPointer();
7781   int *cip=cI->getPointer();
7782   *cip++=0;
7783   for(int i=0;i<nbOfTuples;i++)
7784     {
7785       *cp++=INTERP_KERNEL::NORM_POINT1;
7786       *cp++=i;
7787       *cip++=2*(i+1);
7788     }
7789   ret->setConnectivity(c,cI,true);
7790   return ret.retn();
7791 }
7792 /*!
7793  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7794  * Cells and nodes of
7795  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7796  *  \param [in] mesh1 - the first mesh.
7797  *  \param [in] mesh2 - the second mesh.
7798  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7799  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7800  *          is no more needed.
7801  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7802  *  \throw If the coordinates array is not set in none of the meshes.
7803  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7804  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7805  */
7806 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7807 {
7808   std::vector<const MEDCouplingUMesh *> tmp(2);
7809   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7810   return MergeUMeshes(tmp);
7811 }
7812
7813 /*!
7814  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7815  * Cells and nodes of
7816  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7817  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7818  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7819  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7820  *          is no more needed.
7821  *  \throw If \a a.size() == 0.
7822  *  \throw If \a a[ *i* ] == NULL.
7823  *  \throw If the coordinates array is not set in none of the meshes.
7824  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7825  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7826  */
7827 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7828 {
7829   std::size_t sz=a.size();
7830   if(sz==0)
7831     return MergeUMeshesLL(a);
7832   for(std::size_t ii=0;ii<sz;ii++)
7833     if(!a[ii])
7834       {
7835         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7836         throw INTERP_KERNEL::Exception(oss.str().c_str());
7837       }
7838   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7839   std::vector< const MEDCouplingUMesh * > aa(sz);
7840   int spaceDim=-3;
7841   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7842     {
7843       const MEDCouplingUMesh *cur=a[i];
7844       const DataArrayDouble *coo=cur->getCoords();
7845       if(coo)
7846         spaceDim=coo->getNumberOfComponents();
7847     }
7848   if(spaceDim==-3)
7849     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7850   for(std::size_t i=0;i<sz;i++)
7851     {
7852       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7853       aa[i]=bb[i];
7854     }
7855   return MergeUMeshesLL(aa);
7856 }
7857
7858 /// @cond INTERNAL
7859
7860 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7861 {
7862   if(a.empty())
7863     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7864   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7865   int meshDim=(*it)->getMeshDimension();
7866   int nbOfCells=(*it)->getNumberOfCells();
7867   int meshLgth=(*it++)->getMeshLength();
7868   for(;it!=a.end();it++)
7869     {
7870       if(meshDim!=(*it)->getMeshDimension())
7871         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7872       nbOfCells+=(*it)->getNumberOfCells();
7873       meshLgth+=(*it)->getMeshLength();
7874     }
7875   std::vector<const MEDCouplingPointSet *> aps(a.size());
7876   std::copy(a.begin(),a.end(),aps.begin());
7877   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7878   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7879   ret->setCoords(pts);
7880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7881   c->alloc(meshLgth,1);
7882   int *cPtr=c->getPointer();
7883   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7884   cI->alloc(nbOfCells+1,1);
7885   int *cIPtr=cI->getPointer();
7886   *cIPtr++=0;
7887   int offset=0;
7888   int offset2=0;
7889   for(it=a.begin();it!=a.end();it++)
7890     {
7891       int curNbOfCell=(*it)->getNumberOfCells();
7892       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7893       const int *curC=(*it)->_nodal_connec->getConstPointer();
7894       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7895       for(int j=0;j<curNbOfCell;j++)
7896         {
7897           const int *src=curC+curCI[j];
7898           *cPtr++=*src++;
7899           for(;src!=curC+curCI[j+1];src++,cPtr++)
7900             {
7901               if(*src!=-1)
7902                 *cPtr=*src+offset2;
7903               else
7904                 *cPtr=-1;
7905             }
7906         }
7907       offset+=curCI[curNbOfCell];
7908       offset2+=(*it)->getNumberOfNodes();
7909     }
7910   //
7911   ret->setConnectivity(c,cI,true);
7912   return ret.retn();
7913 }
7914
7915 /// @endcond
7916
7917 /*!
7918  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7919  * dimension and sharing the node coordinates array.
7920  * All cells of the first mesh precede all cells of the second mesh
7921  * within the result mesh. 
7922  *  \param [in] mesh1 - the first mesh.
7923  *  \param [in] mesh2 - the second mesh.
7924  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7925  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7926  *          is no more needed.
7927  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7928  *  \throw If the meshes do not share the node coordinates array.
7929  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7930  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7931  */
7932 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7933 {
7934   std::vector<const MEDCouplingUMesh *> tmp(2);
7935   tmp[0]=mesh1; tmp[1]=mesh2;
7936   return MergeUMeshesOnSameCoords(tmp);
7937 }
7938
7939 /*!
7940  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7941  * dimension and sharing the node coordinates array.
7942  * All cells of the *i*-th mesh precede all cells of the
7943  * (*i*+1)-th mesh within the result mesh.
7944  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7945  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7946  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7947  *          is no more needed.
7948  *  \throw If \a a.size() == 0.
7949  *  \throw If \a a[ *i* ] == NULL.
7950  *  \throw If the meshes do not share the node coordinates array.
7951  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7952  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7953  */
7954 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7955 {
7956   if(meshes.empty())
7957     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7958   for(std::size_t ii=0;ii<meshes.size();ii++)
7959     if(!meshes[ii])
7960       {
7961         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7962         throw INTERP_KERNEL::Exception(oss.str().c_str());
7963       }
7964   const DataArrayDouble *coords=meshes.front()->getCoords();
7965   int meshDim=meshes.front()->getMeshDimension();
7966   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7967   int meshLgth=0;
7968   int meshIndexLgth=0;
7969   for(;iter!=meshes.end();iter++)
7970     {
7971       if(coords!=(*iter)->getCoords())
7972         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7973       if(meshDim!=(*iter)->getMeshDimension())
7974         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7975       meshLgth+=(*iter)->getMeshLength();
7976       meshIndexLgth+=(*iter)->getNumberOfCells();
7977     }
7978   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7979   nodal->alloc(meshLgth,1);
7980   int *nodalPtr=nodal->getPointer();
7981   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7982   nodalIndex->alloc(meshIndexLgth+1,1);
7983   int *nodalIndexPtr=nodalIndex->getPointer();
7984   int offset=0;
7985   for(iter=meshes.begin();iter!=meshes.end();iter++)
7986     {
7987       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7988       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7989       int nbOfCells=(*iter)->getNumberOfCells();
7990       int meshLgth2=(*iter)->getMeshLength();
7991       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7992       if(iter!=meshes.begin())
7993         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7994       else
7995         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7996       offset+=meshLgth2;
7997     }
7998   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7999   ret->setName("merge");
8000   ret->setMeshDimension(meshDim);
8001   ret->setConnectivity(nodal,nodalIndex,true);
8002   ret->setCoords(coords);
8003   return ret;
8004 }
8005
8006 /*!
8007  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
8008  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
8009  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
8010  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
8011  * New" mode are returned for each input mesh.
8012  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
8013  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
8014  *          valid values [0,1,2], see zipConnectivityTraducer().
8015  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
8016  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
8017  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
8018  *          no more needed.
8019  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
8020  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8021  *          is no more needed.
8022  *  \throw If \a meshes.size() == 0.
8023  *  \throw If \a meshes[ *i* ] == NULL.
8024  *  \throw If the meshes do not share the node coordinates array.
8025  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
8026  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
8027  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
8028  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
8029  */
8030 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
8031 {
8032   //All checks are delegated to MergeUMeshesOnSameCoords
8033   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
8034   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
8035   corr.resize(meshes.size());
8036   std::size_t nbOfMeshes=meshes.size();
8037   int offset=0;
8038   const int *o2nPtr=o2n->getConstPointer();
8039   for(std::size_t i=0;i<nbOfMeshes;i++)
8040     {
8041       DataArrayInt *tmp=DataArrayInt::New();
8042       int curNbOfCells=meshes[i]->getNumberOfCells();
8043       tmp->alloc(curNbOfCells,1);
8044       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8045       offset+=curNbOfCells;
8046       tmp->setName(meshes[i]->getName());
8047       corr[i]=tmp;
8048     }
8049   return ret.retn();
8050 }
8051
8052 /*!
8053  * Makes all given meshes share the nodal connectivity array. The common connectivity
8054  * array is created by concatenating the connectivity arrays of all given meshes. All
8055  * the given meshes must be of the same space dimension but dimension of cells **can
8056  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8057  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8058  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8059  *  \param [in,out] meshes - a vector of meshes to update.
8060  *  \throw If any of \a meshes is NULL.
8061  *  \throw If the coordinates array is not set in any of \a meshes.
8062  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8063  *  \throw If \a meshes are of different space dimension.
8064  */
8065 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8066 {
8067   std::size_t sz=meshes.size();
8068   if(sz==0 || sz==1)
8069     return;
8070   std::vector< const DataArrayDouble * > coords(meshes.size());
8071   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8072   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8073     {
8074       if((*it))
8075         {
8076           (*it)->checkConnectivityFullyDefined();
8077           const DataArrayDouble *coo=(*it)->getCoords();
8078           if(coo)
8079             *it2=coo;
8080           else
8081             {
8082               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8083               oss << " has no coordinate array defined !";
8084               throw INTERP_KERNEL::Exception(oss.str().c_str());
8085             }
8086         }
8087       else
8088         {
8089           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8090           oss << " is null !";
8091           throw INTERP_KERNEL::Exception(oss.str().c_str());
8092         }
8093     }
8094   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8095   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8096   int offset=(*it)->getNumberOfNodes();
8097   (*it++)->setCoords(res);
8098   for(;it!=meshes.end();it++)
8099     {
8100       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8101       (*it)->setCoords(res);
8102       (*it)->shiftNodeNumbersInConn(offset);
8103       offset+=oldNumberOfNodes;
8104     }
8105 }
8106
8107 /*!
8108  * Merges nodes coincident with a given precision within all given meshes that share
8109  * the nodal connectivity array. The given meshes **can be of different** mesh
8110  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8111  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8112  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8113  *  \param [in,out] meshes - a vector of meshes to update.
8114  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8115  *  \throw If any of \a meshes is NULL.
8116  *  \throw If the \a meshes do not share the same node coordinates array.
8117  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8118  */
8119 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8120 {
8121   if(meshes.empty())
8122     return ;
8123   std::set<const DataArrayDouble *> s;
8124   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8125     {
8126       if(*it)
8127         s.insert((*it)->getCoords());
8128       else
8129         {
8130           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 !";
8131           throw INTERP_KERNEL::Exception(oss.str().c_str());
8132         }
8133     }
8134   if(s.size()!=1)
8135     {
8136       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 !";
8137       throw INTERP_KERNEL::Exception(oss.str().c_str());
8138     }
8139   const DataArrayDouble *coo=*(s.begin());
8140   if(!coo)
8141     return;
8142   //
8143   DataArrayInt *comm,*commI;
8144   coo->findCommonTuples(eps,-1,comm,commI);
8145   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8146   int oldNbOfNodes=coo->getNumberOfTuples();
8147   int newNbOfNodes;
8148   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8149   if(oldNbOfNodes==newNbOfNodes)
8150     return ;
8151   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8152   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8153     {
8154       (*it)->renumberNodesInConn(o2n->getConstPointer());
8155       (*it)->setCoords(newCoords);
8156     } 
8157 }
8158
8159 /*!
8160  * 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.
8161  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8162  * \param isQuad specifies the policy of connectivity.
8163  * @ret in/out parameter in which the result will be append
8164  */
8165 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8166 {
8167   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8168   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8169   ret.push_back(cm.getExtrudedType());
8170   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8171   switch(flatType)
8172   {
8173     case INTERP_KERNEL::NORM_POINT1:
8174       {
8175         ret.push_back(connBg[1]);
8176         ret.push_back(connBg[1]+nbOfNodesPerLev);
8177         break;
8178       }
8179     case INTERP_KERNEL::NORM_SEG2:
8180       {
8181         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8182         ret.insert(ret.end(),conn,conn+4);
8183         break;
8184       }
8185     case INTERP_KERNEL::NORM_SEG3:
8186       {
8187         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8188         ret.insert(ret.end(),conn,conn+8);
8189         break;
8190       }
8191     case INTERP_KERNEL::NORM_QUAD4:
8192       {
8193         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8194         ret.insert(ret.end(),conn,conn+8);
8195         break;
8196       }
8197     case INTERP_KERNEL::NORM_TRI3:
8198       {
8199         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8200         ret.insert(ret.end(),conn,conn+6);
8201         break;
8202       }
8203     case INTERP_KERNEL::NORM_TRI6:
8204       {
8205         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,
8206           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8207         ret.insert(ret.end(),conn,conn+15);
8208         break;
8209       }
8210     case INTERP_KERNEL::NORM_QUAD8:
8211       {
8212         int conn[20]={
8213           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8214           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8215           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8216         };
8217         ret.insert(ret.end(),conn,conn+20);
8218         break;
8219       }
8220     case INTERP_KERNEL::NORM_POLYGON:
8221       {
8222         std::back_insert_iterator< std::vector<int> > ii(ret);
8223         std::copy(connBg+1,connEnd,ii);
8224         *ii++=-1;
8225         std::reverse_iterator<const int *> rConnBg(connEnd);
8226         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8227         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8228         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8229         for(std::size_t i=0;i<nbOfRadFaces;i++)
8230           {
8231             *ii++=-1;
8232             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8233             std::copy(conn,conn+4,ii);
8234           }
8235         break;
8236       }
8237     default:
8238       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8239   }
8240 }
8241
8242 /*!
8243  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8244  */
8245 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8246 {
8247   std::size_t i, ip1;
8248   double v[3]={0.,0.,0.};
8249   std::size_t sz=std::distance(begin,end);
8250   if(isQuadratic)
8251     sz/=2;
8252   for(i=0;i<sz;i++)
8253     {
8254       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];
8255       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8256       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8257     }
8258   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8259
8260   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8261   // SEG3 forming a circle):
8262   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8263     {
8264       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8265       for(std::size_t j=0;j<sz;j++)
8266         {
8267           if (j%2)  // current point i is quadratic, next point i+1 is standard
8268             {
8269               i = sz+j;
8270               ip1 = (j+1)%sz; // ip1 = "i+1"
8271             }
8272           else      // current point i is standard, next point i+1 is quadratic
8273             {
8274               i = j;
8275               ip1 = j+sz;
8276             }
8277           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8278           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8279           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8280         }
8281       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8282     }
8283   return (ret>0.);
8284 }
8285
8286 /*!
8287  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8288  */
8289 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8290 {
8291   std::vector<std::pair<int,int> > edges;
8292   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8293   const int *bgFace=begin;
8294   for(std::size_t i=0;i<nbOfFaces;i++)
8295     {
8296       const int *endFace=std::find(bgFace+1,end,-1);
8297       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8298       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8299         {
8300           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8301           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8302             return false;
8303           edges.push_back(p1);
8304         }
8305       bgFace=endFace+1;
8306     }
8307   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8308 }
8309
8310 /*!
8311  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8312  */
8313 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8314 {
8315   double vec0[3],vec1[3];
8316   std::size_t sz=std::distance(begin,end);
8317   if(sz%2!=0)
8318     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8319   int nbOfNodes=(int)sz/2;
8320   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8321   const double *pt0=coords+3*begin[0];
8322   const double *pt1=coords+3*begin[nbOfNodes];
8323   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8324   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8325 }
8326
8327 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8328 {
8329   std::size_t sz=std::distance(begin,end);
8330   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8331   std::size_t nbOfNodes(sz/2);
8332   std::copy(begin,end,(int *)tmp);
8333   for(std::size_t j=1;j<nbOfNodes;j++)
8334     {
8335       begin[j]=tmp[nbOfNodes-j];
8336       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8337     }
8338 }
8339
8340 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8341 {
8342   std::size_t sz=std::distance(begin,end);
8343   if(sz!=4)
8344     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8345   double vec0[3],vec1[3];
8346   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8347   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]; 
8348   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;
8349 }
8350
8351 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8352 {
8353   std::size_t sz=std::distance(begin,end);
8354   if(sz!=5)
8355     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8356   double vec0[3];
8357   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8358   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8359   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8360 }
8361
8362 /*!
8363  * 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 ) 
8364  * 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
8365  * a 2D space.
8366  *
8367  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8368  * \param [in] coords the coordinates with nb of components exactly equal to 3
8369  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8370  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8371  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8372  */
8373 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8374 {
8375   int nbFaces=std::count(begin+1,end,-1)+1;
8376   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8377   double *vPtr=v->getPointer();
8378   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8379   double *pPtr=p->getPointer();
8380   const int *stFaceConn=begin+1;
8381   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8382     {
8383       const int *endFaceConn=std::find(stFaceConn,end,-1);
8384       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8385       stFaceConn=endFaceConn+1;
8386     }
8387   pPtr=p->getPointer(); vPtr=v->getPointer();
8388   DataArrayInt *comm1=0,*commI1=0;
8389   v->findCommonTuples(eps,-1,comm1,commI1);
8390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8391   const int *comm1Ptr=comm1->getConstPointer();
8392   const int *commI1Ptr=commI1->getConstPointer();
8393   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8394   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8395   //
8396   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8397   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8398   mm->finishInsertingCells();
8399   //
8400   for(int i=0;i<nbOfGrps1;i++)
8401     {
8402       int vecId=comm1Ptr[commI1Ptr[i]];
8403       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8404       DataArrayInt *comm2=0,*commI2=0;
8405       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8406       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8407       const int *comm2Ptr=comm2->getConstPointer();
8408       const int *commI2Ptr=commI2->getConstPointer();
8409       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8410       for(int j=0;j<nbOfGrps2;j++)
8411         {
8412           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8413             {
8414               res->insertAtTheEnd(begin,end);
8415               res->pushBackSilent(-1);
8416             }
8417           else
8418             {
8419               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8420               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8421               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8422               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8423               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8424               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8425               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8426               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8427               const int *idsNodePtr=idsNode->getConstPointer();
8428               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];
8429               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8430               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8431               if(std::abs(norm)>eps)
8432                 {
8433                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8434                   mm3->rotate(center,vec,angle);
8435                 }
8436               mm3->changeSpaceDimension(2);
8437               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8438               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8439               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8440               int nbOfCells=mm4->getNumberOfCells();
8441               for(int k=0;k<nbOfCells;k++)
8442                 {
8443                   int l=0;
8444                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8445                     res->pushBackSilent(idsNodePtr[*work]);
8446                   res->pushBackSilent(-1);
8447                 }
8448             }
8449         }
8450     }
8451   res->popBackSilent();
8452 }
8453
8454 /*!
8455  * 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
8456  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8457  * 
8458  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8459  * \param [in] coords coordinates expected to have 3 components.
8460  * \param [in] begin start of the nodal connectivity of the face.
8461  * \param [in] end end of the nodal connectivity (excluded) of the face.
8462  * \param [out] v the normalized vector of size 3
8463  * \param [out] p the pos of plane
8464  */
8465 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8466 {
8467   std::size_t nbPoints=std::distance(begin,end);
8468   if(nbPoints<3)
8469     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8470   double vec[3]={0.,0.,0.};
8471   std::size_t j=0;
8472   bool refFound=false;
8473   for(;j<nbPoints-1 && !refFound;j++)
8474     {
8475       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8476       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8477       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8478       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8479       if(norm>eps)
8480         {
8481           refFound=true;
8482           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8483         }
8484     }
8485   for(std::size_t i=j;i<nbPoints-1;i++)
8486     {
8487       double curVec[3];
8488       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8489       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8490       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8491       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8492       if(norm<eps)
8493         continue;
8494       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8495       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];
8496       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8497       if(norm>eps)
8498         {
8499           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8500           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8501           return ;
8502         }
8503     }
8504   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8505 }
8506
8507 /*!
8508  * This method tries to obtain a well oriented polyhedron.
8509  * If the algorithm fails, an exception will be thrown.
8510  */
8511 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8512 {
8513   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8514   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8515   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8516   isPerm[0]=true;
8517   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8518   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8519   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8520   //
8521   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8522     {
8523       bgFace=begin;
8524       std::size_t smthChanged=0;
8525       for(std::size_t i=0;i<nbOfFaces;i++)
8526         {
8527           endFace=std::find(bgFace+1,end,-1);
8528           nbOfEdgesInFace=std::distance(bgFace,endFace);
8529           if(!isPerm[i])
8530             {
8531               bool b;
8532               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8533                 {
8534                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8535                   std::pair<int,int> p2(p1.second,p1.first);
8536                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8537                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8538                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8539                 }
8540               if(isPerm[i])
8541                 { 
8542                   if(!b)
8543                     std::reverse(bgFace+1,endFace);
8544                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8545                     {
8546                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8547                       std::pair<int,int> p2(p1.second,p1.first);
8548                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8549                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8550                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8551                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8552                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8553                       if(it!=edgesOK.end())
8554                         {
8555                           edgesOK.erase(it);
8556                           edgesFinished.push_back(p1);
8557                         }
8558                       else
8559                         edgesOK.push_back(p1);
8560                     }
8561                 }
8562             }
8563           bgFace=endFace+1;
8564         }
8565       if(smthChanged==0)
8566         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8567     }
8568   if(!edgesOK.empty())
8569     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8570   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8571     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8572       bgFace=begin;
8573       for(std::size_t i=0;i<nbOfFaces;i++)
8574         {
8575           endFace=std::find(bgFace+1,end,-1);
8576           std::reverse(bgFace+1,endFace);
8577           bgFace=endFace+1;
8578         }
8579     }
8580 }
8581
8582 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8583 {
8584   int nbOfNodesExpected(skin->getNumberOfNodes());
8585   const int *n2oPtr(n2o->getConstPointer());
8586   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8587   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8588   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8589   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8590   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8591   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8592   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8593   if(nbOfNodesExpected<1)
8594     return ret.retn();
8595   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8596   *work++=n2oPtr[prevNode];
8597   for(int i=1;i<nbOfNodesExpected;i++)
8598     {
8599       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8600         {
8601           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8602           conn.erase(prevNode);
8603           if(conn.size()==1)
8604             {
8605               int curNode(*(conn.begin()));
8606               *work++=n2oPtr[curNode];
8607               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8608               shar.erase(prevCell);
8609               if(shar.size()==1)
8610                 {
8611                   prevCell=*(shar.begin());
8612                   prevNode=curNode;
8613                 }
8614               else
8615                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8616             }
8617           else
8618             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8619         }
8620       else
8621         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8622     }
8623   return ret.retn();
8624 }
8625
8626 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8627 {
8628   int nbOfNodesExpected(skin->getNumberOfNodes());
8629   int nbOfTurn(nbOfNodesExpected/2);
8630   const int *n2oPtr(n2o->getConstPointer());
8631   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8632   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8633   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8634   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8635   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8636   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8637   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8638   if(nbOfNodesExpected<1)
8639     return ret.retn();
8640   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8641   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8642   for(int i=1;i<nbOfTurn;i++)
8643     {
8644       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8645         {
8646           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8647           conn.erase(prevNode);
8648           if(conn.size()==1)
8649             {
8650               int curNode(*(conn.begin()));
8651               *work=n2oPtr[curNode];
8652               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8653               shar.erase(prevCell);
8654               if(shar.size()==1)
8655                 {
8656                   int curCell(*(shar.begin()));
8657                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8658                   prevCell=curCell;
8659                   prevNode=curNode;
8660                   work++;
8661                 }
8662               else
8663                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8664             }
8665           else
8666             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8667         }
8668       else
8669         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8670     }
8671   return ret.retn();
8672 }
8673
8674 /*!
8675  * This method makes the assumption spacedimension == meshdimension == 2.
8676  * This method works only for linear cells.
8677  * 
8678  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8679  */
8680 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8681 {
8682   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8683     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8684   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8685   int oldNbOfNodes(skin->getNumberOfNodes());
8686   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8687   int nbOfNodesExpected(skin->getNumberOfNodes());
8688   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8689   int nbCells(skin->getNumberOfCells());
8690   if(nbCells==nbOfNodesExpected)
8691     return buildUnionOf2DMeshLinear(skin,n2o);
8692   else if(2*nbCells==nbOfNodesExpected)
8693     return buildUnionOf2DMeshQuadratic(skin,n2o);
8694   else
8695     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8696 }
8697
8698 /*!
8699  * This method makes the assumption spacedimension == meshdimension == 3.
8700  * This method works only for linear cells.
8701  * 
8702  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8703  */
8704 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8705 {
8706   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8707     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8708   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8709   const int *conn=m->getNodalConnectivity()->getConstPointer();
8710   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8711   int nbOfCells=m->getNumberOfCells();
8712   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8713   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8714   if(nbOfCells<1)
8715     return ret.retn();
8716   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8717   for(int i=1;i<nbOfCells;i++)
8718     {
8719       *work++=-1;
8720       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8721     }
8722   return ret.retn();
8723 }
8724
8725 /*!
8726  * \brief Creates a graph of cell neighbors
8727  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8728  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
8729  *  For example
8730  *  - index:  0 3 5 6 6
8731  *  - value:  1 2 3 2 3 3
8732  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8733  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8734  */
8735 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8736 {
8737   checkConnectivityFullyDefined();
8738
8739   int meshDim = this->getMeshDimension();
8740   ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8741   ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8742   this->getReverseNodalConnectivity(revConn,indexr);
8743   const int* indexr_ptr=indexr->getConstPointer();
8744   const int* revConn_ptr=revConn->getConstPointer();
8745
8746   const ParaMEDMEM::DataArrayInt* index;
8747   const ParaMEDMEM::DataArrayInt* conn;
8748   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8749   index=this->getNodalConnectivityIndex();
8750   int nbCells=this->getNumberOfCells();
8751   const int* index_ptr=index->getConstPointer();
8752   const int* conn_ptr=conn->getConstPointer();
8753
8754   //creating graph arcs (cell to cell relations)
8755   //arcs are stored in terms of (index,value) notation
8756   // 0 3 5 6 6
8757   // 1 2 3 2 3 3
8758   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8759   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8760
8761   //warning here one node have less than or equal effective number of cell with it
8762   //but cell could have more than effective nodes
8763   //because other equals nodes in other domain (with other global inode)
8764   std::vector <int> cell2cell_index(nbCells+1,0);
8765   std::vector <int> cell2cell;
8766   cell2cell.reserve(3*nbCells);
8767
8768   for (int icell=0; icell<nbCells;icell++)
8769     {
8770       std::map<int,int > counter;
8771       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8772         {
8773           int inode=conn_ptr[iconn];
8774           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8775             {
8776               int icell2=revConn_ptr[iconnr];
8777               std::map<int,int>::iterator iter=counter.find(icell2);
8778               if (iter!=counter.end()) (iter->second)++;
8779               else counter.insert(std::make_pair(icell2,1));
8780             }
8781         }
8782       for (std::map<int,int>::const_iterator iter=counter.begin();
8783            iter!=counter.end(); iter++)
8784         if (iter->second >= meshDim)
8785           {
8786             cell2cell_index[icell+1]++;
8787             cell2cell.push_back(iter->first);
8788           }
8789     }
8790   indexr->decrRef();
8791   revConn->decrRef();
8792   cell2cell_index[0]=0;
8793   for (int icell=0; icell<nbCells;icell++)
8794     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8795
8796   //filling up index and value to create skylinearray structure
8797   MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8798   return array;
8799 }
8800
8801 /*!
8802  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8803  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8804  */
8805 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8806 {
8807   double *w=zipFrmt;
8808   if(spaceDim==3)
8809     for(int i=0;i<nbOfNodesInCell;i++)
8810       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8811   else if(spaceDim==2)
8812     {
8813       for(int i=0;i<nbOfNodesInCell;i++)
8814         {
8815           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8816           *w++=0.;
8817         }
8818     }
8819   else
8820     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8821 }
8822
8823 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8824 {
8825   int nbOfCells=getNumberOfCells();
8826   if(nbOfCells<=0)
8827     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8828   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};
8829   ofs << "  <" << getVTKDataSetType() << ">\n";
8830   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8831   ofs << "      <PointData>\n" << pointData << std::endl;
8832   ofs << "      </PointData>\n";
8833   ofs << "      <CellData>\n" << cellData << std::endl;
8834   ofs << "      </CellData>\n";
8835   ofs << "      <Points>\n";
8836   if(getSpaceDimension()==3)
8837     _coords->writeVTK(ofs,8,"Points",byteData);
8838   else
8839     {
8840       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8841       coo->writeVTK(ofs,8,"Points",byteData);
8842     }
8843   ofs << "      </Points>\n";
8844   ofs << "      <Cells>\n";
8845   const int *cPtr=_nodal_connec->getConstPointer();
8846   const int *cIPtr=_nodal_connec_index->getConstPointer();
8847   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8848   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8849   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8850   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8851   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8852   int szFaceOffsets=0,szConn=0;
8853   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8854     {
8855       *w2=cPtr[cIPtr[i]];
8856       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8857         {
8858           *w1=-1;
8859           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8860           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8861         }
8862       else
8863         {
8864           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8865           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8866           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8867           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8868           w4=std::copy(c.begin(),c.end(),w4);
8869         }
8870     }
8871   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8872   types->writeVTK(ofs,8,"UInt8","types",byteData);
8873   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8874   if(szFaceOffsets!=0)
8875     {//presence of Polyhedra
8876       connectivity->reAlloc(szConn);
8877       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8878       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8879       w1=faces->getPointer();
8880       for(int i=0;i<nbOfCells;i++)
8881         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8882           {
8883             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8884             *w1++=nbFaces;
8885             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8886             for(int j=0;j<nbFaces;j++)
8887               {
8888                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8889                 *w1++=(int)std::distance(w6,w5);
8890                 w1=std::copy(w6,w5,w1);
8891                 w6=w5+1;
8892               }
8893           }
8894       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8895     }
8896   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8897   ofs << "      </Cells>\n";
8898   ofs << "    </Piece>\n";
8899   ofs << "  </" << getVTKDataSetType() << ">\n";
8900 }
8901
8902 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8903 {
8904   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8905   if(_mesh_dim==-2)
8906     { stream << " Not set !"; return ; }
8907   stream << " Mesh dimension : " << _mesh_dim << ".";
8908   if(_mesh_dim==-1)
8909     return ;
8910   if(!_coords)
8911     { stream << " No coordinates set !"; return ; }
8912   if(!_coords->isAllocated())
8913     { stream << " Coordinates set but not allocated !"; return ; }
8914   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8915   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8916   if(!_nodal_connec_index)
8917     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8918   if(!_nodal_connec_index->isAllocated())
8919     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8920   int lgth=_nodal_connec_index->getNumberOfTuples();
8921   int cpt=_nodal_connec_index->getNumberOfComponents();
8922   if(cpt!=1 || lgth<1)
8923     return ;
8924   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8925 }
8926
8927 std::string MEDCouplingUMesh::getVTKDataSetType() const
8928 {
8929   return std::string("UnstructuredGrid");
8930 }
8931
8932 std::string MEDCouplingUMesh::getVTKFileExtension() const
8933 {
8934   return std::string("vtu");
8935 }
8936
8937 /*!
8938  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8939  * returns a result mesh constituted by polygons.
8940  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8941  * all nodes from m2.
8942  * The meshes should be in 2D space. In
8943  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8944  * meshes.
8945  *  \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
8946  *                      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)
8947  *  \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
8948  *                      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)
8949  *  \param [in] eps - precision used to detect coincident mesh entities.
8950  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8951  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8952  *         this array using decrRef() as it is no more needed.
8953  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8954  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8955  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8956  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8957  *         it is no more needed.  
8958  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8959  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8960  *         is no more needed.  
8961  *  \throw If the coordinates array is not set in any of the meshes.
8962  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8963  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8964  *
8965  *  \sa conformize2D, mergeNodes
8966  */
8967 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8968                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8969 {
8970   if(!m1 || !m2)
8971     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8972   m1->checkFullyDefined();
8973   m2->checkFullyDefined();
8974   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8975     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8976
8977   // Step 1: compute all edge intersections (new nodes)
8978   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8979   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8980   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8981   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8982   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8983                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8984                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8985   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8986   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8987   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8988
8989   // Step 2: re-order newly created nodes according to the ordering found in m2
8990   std::vector< std::vector<int> > intersectEdge2;
8991   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8992   subDiv2.clear(); dd5=0; dd6=0;
8993
8994   // Step 3:
8995   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8996   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8997   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8998                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8999
9000   // Step 4: Prepare final result:
9001   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9002   addCooDa->alloc((int)(addCoo.size())/2,2);
9003   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
9004   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
9005   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
9006   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
9007   std::vector<const DataArrayDouble *> coordss(4);
9008   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
9009   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
9010   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
9011   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
9012   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
9013   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
9014   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
9015   ret->setConnectivity(conn,connI,true);
9016   ret->setCoords(coo);
9017   cellNb1=c1.retn(); cellNb2=c2.retn();
9018   return ret.retn();
9019 }
9020
9021 /// @cond INTERNAL
9022
9023 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
9024 {
9025   if(candidates.empty())
9026     return false;
9027   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
9028     {
9029       const std::vector<int>& pool(intersectEdge1[*it]);
9030       int tmp[2]; tmp[0]=start; tmp[1]=stop;
9031       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9032         {
9033           retVal=*it+1;
9034           return true;
9035         }
9036       tmp[0]=stop; tmp[1]=start;
9037       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
9038         {
9039           retVal=-*it-1;
9040           return true;
9041         }
9042     }
9043   return false;
9044 }
9045
9046 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,
9047                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9048 {
9049   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9050   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9051   int nCells(mesh1D->getNumberOfCells());
9052   if(nCells!=(int)intersectEdge2.size())
9053     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9054   const DataArrayDouble *coo2(mesh1D->getCoords());
9055   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9056   const double *coo2Ptr(coo2->begin());
9057   int offset1(coords1->getNumberOfTuples());
9058   int offset2(offset1+coo2->getNumberOfTuples());
9059   int offset3(offset2+addCoo.size()/2);
9060   std::vector<double> addCooQuad;
9061   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9062   int tmp[4],cicnt(0),kk(0);
9063   for(int i=0;i<nCells;i++)
9064     {
9065       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9066       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9067       const std::vector<int>& subEdges(intersectEdge2[i]);
9068       int nbSubEdge(subEdges.size()/2);
9069       for(int j=0;j<nbSubEdge;j++,kk++)
9070         {
9071           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));
9072           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9073           INTERP_KERNEL::Edge *e2Ptr(e2);
9074           std::map<int,int>::const_iterator itm;
9075           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9076             {
9077               tmp[0]=INTERP_KERNEL::NORM_SEG3;
9078               itm=mergedNodes.find(subEdges[2*j]);
9079               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9080               itm=mergedNodes.find(subEdges[2*j+1]);
9081               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9082               tmp[3]=offset3+(int)addCooQuad.size()/2;
9083               double tmp2[2];
9084               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9085               cicnt+=4;
9086               cOut->insertAtTheEnd(tmp,tmp+4);
9087               ciOut->pushBackSilent(cicnt);
9088             }
9089           else
9090             {
9091               tmp[0]=INTERP_KERNEL::NORM_SEG2;
9092               itm=mergedNodes.find(subEdges[2*j]);
9093               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9094               itm=mergedNodes.find(subEdges[2*j+1]);
9095               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9096               cicnt+=3;
9097               cOut->insertAtTheEnd(tmp,tmp+3);
9098               ciOut->pushBackSilent(cicnt);
9099             }
9100           int tmp00;
9101           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9102             {
9103               idsInRetColinear->pushBackSilent(kk);
9104               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9105             }
9106         }
9107       e->decrRef();
9108     }
9109   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9110   ret->setConnectivity(cOut,ciOut,true);
9111   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9112   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9113   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9114   std::vector<const DataArrayDouble *> coordss(4);
9115   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9116   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9117   ret->setCoords(arr);
9118   return ret.retn();
9119 }
9120
9121 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9122 {
9123   std::vector<int> allEdges;
9124   for(const int *it2(descBg);it2!=descEnd;it2++)
9125     {
9126       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9127       if(*it2>0)
9128         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9129       else
9130         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9131     }
9132   std::size_t nb(allEdges.size());
9133   if(nb%2!=0)
9134     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9135   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9136   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9137   ret->setCoords(coords);
9138   ret->allocateCells(1);
9139   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9140   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9141     connOut[kk]=allEdges[2*kk];
9142   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9143   return ret.retn();
9144 }
9145
9146 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9147 {
9148   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9149   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9150   std::size_t ii(0);
9151   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9152   if(sz!=std::distance(descBg,descEnd))
9153     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9154   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9155   std::vector<int> allEdges,centers;
9156   const double *coordsPtr(coords->begin());
9157   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9158   int offset(coords->getNumberOfTuples());
9159   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9160     {
9161       INTERP_KERNEL::NormalizedCellType typeOfSon;
9162       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9163       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9164       if(*it2>0)
9165         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9166       else
9167         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9168       if(edge1.size()==2)
9169         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9170       else
9171         {//the current edge has been subsplit -> create corresponding centers.
9172           std::size_t nbOfCentersToAppend(edge1.size()/2);
9173           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9174           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9175           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9176           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9177             {
9178               double tmpp[2];
9179               const double *aa(coordsPtr+2*(*it3++));
9180               const double *bb(coordsPtr+2*(*it3++));
9181               ee->getMiddleOfPoints(aa,bb,tmpp);
9182               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9183               centers.push_back(offset+k);
9184             }
9185         }
9186     }
9187   std::size_t nb(allEdges.size());
9188   if(nb%2!=0)
9189     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9190   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9191   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9192   if(addCoo->empty())
9193     ret->setCoords(coords);
9194   else
9195     {
9196       addCoo->rearrange(2);
9197       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9198       ret->setCoords(addCoo);
9199     }
9200   ret->allocateCells(1);
9201   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9202   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9203     connOut[kk]=allEdges[2*kk];
9204   connOut.insert(connOut.end(),centers.begin(),centers.end());
9205   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9206   return ret.retn();
9207 }
9208
9209 /*!
9210  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9211  * of those edges.
9212  *
9213  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9214  */
9215 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9216 {
9217   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9218   if(!cm.isQuadratic())
9219     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9220   else
9221     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9222 }
9223
9224 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9225 {
9226   bool isQuad(false);
9227   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9228     {
9229       const INTERP_KERNEL::Edge *ee(*it);
9230       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9231         isQuad=true;
9232     }
9233   if(!isQuad)
9234     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9235   else
9236     {
9237       const double *coo(mesh2D->getCoords()->begin());
9238       std::size_t sz(conn.size());
9239       std::vector<double> addCoo;
9240       std::vector<int> conn2(conn);
9241       int offset(mesh2D->getNumberOfNodes());
9242       for(std::size_t i=0;i<sz;i++)
9243         {
9244           double tmp[2];
9245           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9246           addCoo.insert(addCoo.end(),tmp,tmp+2);
9247           conn2.push_back(offset+(int)i);
9248         }
9249       mesh2D->getCoords()->rearrange(1);
9250       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9251       mesh2D->getCoords()->rearrange(2);
9252       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9253     }
9254 }
9255
9256 /*!
9257  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9258  *
9259  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9260  * a set of edges defined in \a splitMesh1D.
9261  */
9262 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9263                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9264 {
9265   std::size_t nb(edge1Bis.size()/2);
9266   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9267   int iEnd(splitMesh1D->getNumberOfCells());
9268   if(iEnd==0)
9269     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9270   std::size_t ii,jj;
9271   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9272   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9273   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9274   //
9275   if(jj==nb)
9276     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9277       out0.resize(1); out1.resize(1);
9278       std::vector<int>& connOut(out0[0]);
9279       connOut.resize(nbOfEdgesOf2DCellSplit);
9280       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9281       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9282       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9283         {
9284           connOut[kk]=edge1Bis[2*kk];
9285           edgesPtr[kk]=edge1BisPtr[2*kk];
9286         }
9287     }
9288   else
9289     {
9290       // [i,iEnd[ contains the
9291       out0.resize(2); out1.resize(2);
9292       std::vector<int>& connOutLeft(out0[0]);
9293       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9294       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9295       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9296       for(std::size_t k=ii;k<jj+1;k++)
9297         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9298       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9299       for(int ik=0;ik<iEnd;ik++)
9300         {
9301           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9302           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9303           ees[ik]=ee;
9304         }
9305       for(int ik=iEnd-1;ik>=0;ik--)
9306         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9307       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9308         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9309       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9310       for(int ik=0;ik<iEnd;ik++)
9311         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9312       eright.insert(eright.end(),ees.begin(),ees.end());
9313     }
9314 }
9315
9316 /// @endcond
9317
9318 /// @cond INTERNAL
9319
9320 struct CellInfo
9321 {
9322 public:
9323   CellInfo() { }
9324   CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9325 public:
9326   std::vector<int> _edges;
9327   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9328 };
9329
9330 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9331 {
9332   std::size_t nbe(edges.size());
9333   std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9334   for(std::size_t i=0;i<nbe;i++)
9335     {
9336       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9337       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9338     }
9339   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9340   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9341   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9342 }
9343
9344 class EdgeInfo
9345 {
9346 public:
9347   EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9348   EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9349   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9350   void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9351   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9352 private:
9353   int _istart;
9354   int _iend;
9355   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9356   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9357   int _left;
9358   int _right;
9359 };
9360
9361 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9362 {
9363   const MEDCouplingUMesh *mesh(_mesh);
9364   if(mesh)
9365     return ;
9366   if(_right<pos)
9367     return ;
9368   if(_left>pos)
9369     { _left++; _right++; return ; }
9370   if(_right==pos)
9371     {
9372       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9373       if((isLeft && isRight) || (!isLeft && !isRight))
9374         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9375       if(isLeft)
9376         return ;
9377       if(isRight)
9378         {
9379           _right++;
9380           return ;
9381         }
9382     }
9383   if(_left==pos)
9384     {
9385       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9386       if((isLeft && isRight) || (!isLeft && !isRight))
9387         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9388       if(isLeft)
9389         {
9390           _right++;
9391           return ;
9392         }
9393       if(isRight)
9394         {
9395           _left++;
9396           _right++;
9397           return ;
9398         }
9399     }
9400 }
9401
9402 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9403 {
9404   const MEDCouplingUMesh *mesh(_mesh);
9405   if(!mesh)
9406     {
9407       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9408     }
9409   else
9410     {// not fully splitting cell case
9411       if(mesh2D->getNumberOfCells()==1)
9412         {//little optimization. 1 cell no need to find in which cell mesh is !
9413           neighbors[0]=offset; neighbors[1]=offset;
9414           return;
9415         }
9416       else
9417         {
9418           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9419           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9420           if(cellId==-1)
9421             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9422           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9423         }
9424     }
9425 }
9426
9427 class VectorOfCellInfo
9428 {
9429 public:
9430   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9431   std::size_t size() const { return _pool.size(); }
9432   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9433   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);
9434   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9435   const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9436   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9437   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9438 private:
9439   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9440   void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9441   const CellInfo& get(int pos) const;
9442   CellInfo& get(int pos);
9443 private:
9444   std::vector<CellInfo> _pool;
9445   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9446   std::vector<EdgeInfo> _edge_info;
9447 };
9448
9449 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9450 {
9451   _pool[0]._edges=edges;
9452   _pool[0]._edges_ptr=edgesPtr;
9453 }
9454
9455 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9456 {
9457   if(_pool.empty())
9458     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9459   if(_pool.size()==1)
9460     return 0;
9461   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9462   if(!zeMesh)
9463     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9464   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9465   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9466 }
9467
9468 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)
9469 {
9470   get(pos);//to check pos
9471   bool isFast(pos==0 && _pool.size()==1);
9472   std::size_t sz(edges.size());
9473   // dealing with edges
9474   if(sz==1)
9475     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9476   else
9477     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9478   //
9479   std::vector<CellInfo> pool(_pool.size()-1+sz);
9480   for(int i=0;i<pos;i++)
9481     pool[i]=_pool[i];
9482   for(std::size_t j=0;j<sz;j++)
9483     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9484   for(int i=pos+1;i<(int)_pool.size();i++)
9485     pool[i+sz-1]=_pool[i];
9486   _pool=pool;
9487   //
9488   if(sz==2)
9489     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9490   //
9491   if(isFast)
9492     {
9493       _ze_mesh=mesh;
9494       return ;
9495     }
9496   //
9497   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9498   if(pos>0)
9499     {
9500       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9501       ms.push_back(elt);
9502     }
9503   ms.push_back(mesh);
9504   if(pos<_ze_mesh->getNumberOfCells()-1)
9505   {
9506     MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9507     ms.push_back(elt);
9508   }
9509   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9510   for(std::size_t j=0;j<ms2.size();j++)
9511     ms2[j]=ms[j];
9512   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9513 }
9514
9515 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9516 {
9517   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9518 }
9519
9520 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9521 {
9522   if(pos<0)
9523     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9524   int ret(0);
9525   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9526     {
9527       if((*it).isInMyRange(pos))
9528         return ret;
9529     }
9530   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9531 }
9532
9533 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9534 {
9535   get(pos);//to check;
9536   if(_edge_info.empty())
9537     return ;
9538   std::size_t sz(_edge_info.size()-1);
9539   for(std::size_t i=0;i<sz;i++)
9540     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9541 }
9542
9543 const CellInfo& VectorOfCellInfo::get(int pos) const
9544 {
9545   if(pos<0 || pos>=(int)_pool.size())
9546     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9547   return _pool[pos];
9548 }
9549
9550 CellInfo& VectorOfCellInfo::get(int pos)
9551 {
9552   if(pos<0 || pos>=(int)_pool.size())
9553     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9554   return _pool[pos];
9555 }
9556
9557 /*!
9558  * Given :
9559  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9560  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9561  *
9562  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9563  *
9564  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9565  *
9566  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9567  */
9568 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9569                                          MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9570 {
9571   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9572   if(nbCellsInSplitMesh1D==0)
9573     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9574   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9575   std::size_t nb(allEdges.size()),jj;
9576   if(nb%2!=0)
9577     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9578   std::vector<int> edge1Bis(nb*2);
9579   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9580   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9581   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9582   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9583   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9584   //
9585   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9586   int *idsLeftRightPtr(idsLeftRight->getPointer());
9587   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9588   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9589     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9590       int iEnd(iStart);
9591       for(;iEnd<nbCellsInSplitMesh1D;)
9592         {
9593           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9594           if(jj!=nb)
9595             break;
9596           else
9597             iEnd++;
9598         }
9599       if(iEnd<nbCellsInSplitMesh1D)
9600         iEnd++;
9601       //
9602       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9603       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9604       //
9605       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9606       retTmp->setCoords(splitMesh1D->getCoords());
9607       retTmp->allocateCells();
9608
9609       std::vector< std::vector<int> > out0;
9610       std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9611
9612       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9613       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9614         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9615       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9616       //
9617       iStart=iEnd;
9618     }
9619   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9620     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9621   return pool.getZeMesh().retn();
9622 }
9623
9624 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9625                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9626                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9627 {
9628   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9629   //
9630   std::vector<int> allEdges;
9631   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9632   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9633     {
9634       int edgeId(std::abs(*it)-1);
9635       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9636       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9637       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9638       if(*it>0)
9639         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9640       else
9641         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9642       std::size_t sz(edge1.size());
9643       for(std::size_t cnt=0;cnt<sz;cnt++)
9644         allEdgesPtr.push_back(ee);
9645     }
9646   //
9647   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9648 }
9649
9650 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9651 {
9652   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9653     {//easy case comparison not
9654       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9655     }
9656   else if(typ1.isQuadratic() && typ2.isQuadratic())
9657     {
9658       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9659       if(!status0)
9660         return false;
9661       if(conn1[2]==conn2[2])
9662         return true;
9663       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9664       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9665       return dist<eps;
9666     }
9667   else
9668     {//only one is quadratic
9669       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9670       if(!status0)
9671         return false;
9672       const double *a(0),*bb(0),*be(0);
9673       if(typ1.isQuadratic())
9674         {
9675           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9676         }
9677       else
9678         {
9679           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9680         }
9681       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9682       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9683       return dist<eps;
9684     }
9685 }
9686
9687 /*!
9688  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9689  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9690  *
9691  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9692  */
9693 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9694 {
9695   if(candidatesIn2DEnd==candidatesIn2DBg)
9696     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9697   const double *coo(mesh2DSplit->getCoords()->begin());
9698   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9699     return *candidatesIn2DBg;
9700   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9701   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9702   if(cellIdInMesh1DSplitRelative<0)
9703     cur1D->changeOrientationOfCells();
9704   const int *c1D(cur1D->getNodalConnectivity()->begin());
9705   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9706   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9707     {
9708       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9709       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9710       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9711       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9712       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9713       for(unsigned it2=0;it2<sz;it2++)
9714         {
9715           INTERP_KERNEL::NormalizedCellType typeOfSon;
9716           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9717           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9718           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9719             return *it;
9720         }
9721     }
9722   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9723 }
9724
9725 /// @endcond
9726
9727 /*!
9728  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9729  * 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
9730  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9731  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9732  *
9733  * \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
9734  *                      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)
9735  * \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
9736  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9737  * \param [in] eps - precision used to perform intersections and localization operations.
9738  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9739  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9740  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9741  *                               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.
9742  * \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
9743  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9744  *                               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.
9745  *
9746  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9747  */
9748 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9749 {
9750   if(!mesh2D || !mesh1D)
9751     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9752   mesh2D->checkFullyDefined();
9753   mesh1D->checkFullyDefined();
9754   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9755   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9756     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9757   // Step 1: compute all edge intersections (new nodes)
9758   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9759   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9760   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9761   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9762   //
9763   // Build desc connectivity
9764   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9765   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9766   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9767   std::map<int,int> mergedNodes;
9768   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9769   // use mergeNodes to fix intersectEdge1
9770   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9771     {
9772       std::size_t n((*it0).size()/2);
9773       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9774       std::map<int,int>::const_iterator it1;
9775       it1=mergedNodes.find(eltStart);
9776       if(it1!=mergedNodes.end())
9777         (*it0)[0]=(*it1).second;
9778       it1=mergedNodes.find(eltEnd);
9779       if(it1!=mergedNodes.end())
9780         (*it0)[2*n-1]=(*it1).second;
9781     }
9782   //
9783   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9784   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9785   // Step 2: re-order newly created nodes according to the ordering found in m2
9786   std::vector< std::vector<int> > intersectEdge2;
9787   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9788   subDiv2.clear();
9789   // Step 3: compute splitMesh1D
9790   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9791   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9792   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9793       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9794   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9795   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9796   // deal with cells in mesh2D that are not cut but only some of their edges are
9797   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9798   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9799   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9800   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
9801   if(!idsInDesc2DToBeRefined->empty())
9802     {
9803       DataArrayInt *out0(0),*outi0(0);
9804       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9805       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9806       out0s=out0;
9807       out0s=out0s->buildUnique();
9808       out0s->sort(true);
9809     }
9810   //
9811   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9812   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9813   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9814   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9815   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9816   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9817   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9818     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9819   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9821   if((DataArrayInt *)out0s)
9822     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9823   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9824   // OK all is ready to insert in ret2 mesh
9825   if(!untouchedCells->empty())
9826     {// the most easy part, cells in mesh2D not impacted at all
9827       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9828       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9829       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9830     }
9831   if((DataArrayInt *)out0s)
9832     {// here dealing with cells in out0s but not in cellsToBeModified
9833       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9834       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9835       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9836         {
9837           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9838           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9839         }
9840       int offset(ret2->getNumberOfTuples());
9841       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9842       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9843       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9844       int kk(0),*ret3ptr(partOfRet3->getPointer());
9845       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9846         {
9847           int faceId(std::abs(*it)-1);
9848           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9849             {
9850               int tmp(fewModifiedCells->locateValue(*it2));
9851               if(tmp!=-1)
9852                 {
9853                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9854                     ret3ptr[2*kk]=tmp+offset;
9855                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9856                     ret3ptr[2*kk+1]=tmp+offset;
9857                 }
9858               else
9859                 {//the current edge is shared by a 2D cell that will be split just after
9860                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9861                     ret3ptr[2*kk]=-(*it2+1);
9862                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9863                     ret3ptr[2*kk+1]=-(*it2+1);
9864                 }
9865             }
9866         }
9867       m1Desc->setCoords(ret1->getCoords());
9868       ret1NonCol->setCoords(ret1->getCoords());
9869       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9870       if(!outMesh2DSplit.empty())
9871         {
9872           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9873           for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9874             (*itt)->setCoords(da);
9875         }
9876     }
9877   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9878   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9879     {
9880       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9881       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9882       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9883       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9884       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9885       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));
9886       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9887       outMesh2DSplit.push_back(splitOfOneCell);
9888       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9889         ret2->pushBackSilent(*it);
9890     }
9891   //
9892   std::size_t nbOfMeshes(outMesh2DSplit.size());
9893   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9894   for(std::size_t i=0;i<nbOfMeshes;i++)
9895     tmp[i]=outMesh2DSplit[i];
9896   //
9897   ret1->getCoords()->setInfoOnComponents(compNames);
9898   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9899   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9900   ret3->rearrange(1);
9901   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9902   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9903     {
9904       int old2DCellId(-ret3->getIJ(*it,0)-1);
9905       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9906       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
9907     }
9908   ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9909   ret3->rearrange(2);
9910   //
9911   splitMesh1D=ret1.retn();
9912   splitMesh2D=ret2D.retn();
9913   cellIdInMesh2D=ret2.retn();
9914   cellIdInMesh1D=ret3.retn();
9915 }
9916
9917 /**
9918  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9919  * (newly created) nodes corresponding to the edge intersections.
9920  * Output params:
9921  * @param[out] cr, crI connectivity of the resulting mesh
9922  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9923  * TODO: describe input parameters
9924  */
9925 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9926                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9927                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9928                                                          const std::vector<double>& addCoords,
9929                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9930 {
9931   static const int SPACEDIM=2;
9932   const double *coo1(m1->getCoords()->getConstPointer());
9933   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9934   int offset1(m1->getNumberOfNodes());
9935   const double *coo2(m2->getCoords()->getConstPointer());
9936   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9937   int offset2(offset1+m2->getNumberOfNodes());
9938   int offset3(offset2+((int)addCoords.size())/2);
9939   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9940   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9941   // Here a BBTree on 2D-cells, not on segments:
9942   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9943   int ncell1(m1->getNumberOfCells());
9944   crI.push_back(0);
9945   for(int i=0;i<ncell1;i++)
9946     {
9947       std::vector<int> candidates2;
9948       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9949       std::map<INTERP_KERNEL::Node *,int> mapp;
9950       std::map<int,INTERP_KERNEL::Node *> mappRev;
9951       INTERP_KERNEL::QuadraticPolygon pol1;
9952       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9953       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9954       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9955       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9956       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9957       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9958           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9959       //
9960       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
9961       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9962       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9963       for(it1.first();!it1.finished();it1.next())
9964         edges1.insert(it1.current()->getPtr());
9965       //
9966       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9967       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9968       int ii=0;
9969       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9970         {
9971           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9972           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9973           // Complete mapping with elements coming from the current cell it2 in mesh2:
9974           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9975           // pol2 is the new QP in the final merged result.
9976           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9977               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9978         }
9979       ii=0;
9980       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9981         {
9982           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9983           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9984           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9985           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9986         }
9987       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9988       // by m2 but that we still want to keep in the final result.
9989       if(!edges1.empty())
9990         {
9991           try
9992           {
9993               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9994           }
9995           catch(INTERP_KERNEL::Exception& e)
9996           {
9997               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();
9998               throw INTERP_KERNEL::Exception(oss.str().c_str());
9999           }
10000         }
10001       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
10002         (*it).second->decrRef();
10003     }
10004 }
10005
10006 /**
10007  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
10008  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
10009  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
10010  * The caller is to deal with the resulting DataArrayInt.
10011  *  \throw If the coordinate array is not set.
10012  *  \throw If the nodal connectivity of the cells is not defined.
10013  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
10014  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
10015  *
10016  * \sa DataArrayInt::sortEachPairToMakeALinkedList
10017  */
10018 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
10019 {
10020   checkFullyDefined();
10021   if(getMeshDimension()!=1)
10022     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
10023
10024   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
10025   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
10026   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
10027   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
10028   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
10029   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
10030   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
10031   const int * dsi(_dsi->getConstPointer());
10032   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
10033   m_points=0;
10034   if (dsii->getNumberOfTuples())
10035     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
10036
10037   int nc(getNumberOfCells());
10038   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10039   result->alloc(nc,1);
10040
10041   // set of edges not used so far
10042   std::set<int> edgeSet;
10043   for (int i=0; i<nc; edgeSet.insert(i), i++);
10044
10045   int startSeg=0;
10046   int newIdx=0;
10047   // while we have points with only one neighbor segments
10048   do
10049     {
10050       std::list<int> linePiece;
10051       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10052       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10053         {
10054           // Fill the list forward (resp. backward) from the start segment:
10055           int activeSeg = startSeg;
10056           int prevPointId = -20;
10057           int ptId;
10058           while (!edgeSet.empty())
10059             {
10060               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10061                 {
10062                   if (direction==0)
10063                     linePiece.push_back(activeSeg);
10064                   else
10065                     linePiece.push_front(activeSeg);
10066                   edgeSet.erase(activeSeg);
10067                 }
10068
10069               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10070               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10071               if (dsi[ptId] == 1) // hitting the end of the line
10072                 break;
10073               prevPointId = ptId;
10074               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10075               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10076             }
10077         }
10078       // Done, save final piece into DA:
10079       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10080       newIdx += linePiece.size();
10081
10082       // identify next valid start segment (one which is not consumed)
10083       if(!edgeSet.empty())
10084         startSeg = *(edgeSet.begin());
10085     }
10086   while (!edgeSet.empty());
10087   return result.retn();
10088 }
10089
10090 /// @cond INTERNAL
10091
10092 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10093 {
10094   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10095   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10096   if(it==m.end())
10097     throw INTERP_KERNEL::Exception("Internal error in remapping !");
10098   int v((*it).second);
10099   if(v==forbVal0 || v==forbVal1)
10100     return ;
10101   if(std::find(isect.begin(),isect.end(),v)==isect.end())
10102     isect.push_back(v);
10103 }
10104
10105 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10106 {
10107   int sz(c.size());
10108   if(sz<=1)
10109     return false;
10110   bool presenceOfOn(false);
10111   for(int i=0;i<sz;i++)
10112     {
10113       INTERP_KERNEL::ElementaryEdge *e(c[i]);
10114       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10115         continue ;
10116       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10117       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10118     }
10119   return presenceOfOn;
10120 }
10121
10122 /// @endcond
10123
10124 /**
10125  * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg and in \a subNodesInSegI using index storage mode.
10126  * To do the work this method can optionally needs information about middle of subedges for quadratic cases if a minimal creation of new nodes is wanted.
10127  * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add nodes if a SEG3 is split without information of middle.
10128  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
10129  *
10130  * \return int - the number of new nodes created (in most of cases 0).
10131  * 
10132  * \throw If \a this is not coherent.
10133  * \throw If \a this has not spaceDim equal to 2.
10134  * \throw If \a this has not meshDim equal to 2.
10135  * \throw If some subcells needed to be split are orphan.
10136  * \sa MEDCouplingUMesh::conformize2D
10137  */
10138 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10139 {
10140   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10141     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10142   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10143   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10144     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10145   if(midOpt==0 && midOptI==0)
10146     {
10147       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10148       return 0;
10149     }
10150   else if(midOpt!=0 && midOptI!=0)
10151     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10152   else
10153     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10154 }
10155
10156 /*!
10157  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10158  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10159  * 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
10160  * 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).
10161  * 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.
10162  * 
10163  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10164  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10165  *
10166  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10167  * This method expects that all nodes in \a this are not closer than \a eps.
10168  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10169  * 
10170  * \param [in] eps the relative error to detect merged edges.
10171  * \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
10172  *                           that the user is expected to deal with.
10173  *
10174  * \throw If \a this is not coherent.
10175  * \throw If \a this has not spaceDim equal to 2.
10176  * \throw If \a this has not meshDim equal to 2.
10177  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10178  */
10179 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10180 {
10181   static const int SPACEDIM=2;
10182   checkCoherency();
10183   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10184     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10185   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10186   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10187   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10188   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10189   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10190   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10191   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10192   std::vector<double> addCoo;
10193   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10194   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10195   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10196   for(int i=0;i<nDescCell;i++)
10197     {
10198       std::vector<int> candidates;
10199       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10200       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10201         if(*it>i)
10202           {
10203             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10204             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10205                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10206             INTERP_KERNEL::MergePoints merge;
10207             INTERP_KERNEL::QuadraticPolygon c1,c2;
10208             e1->intersectWith(e2,merge,c1,c2);
10209             e1->decrRef(); e2->decrRef();
10210             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10211               overlapEdge[i].push_back(*it);
10212             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10213               overlapEdge[*it].push_back(i);
10214           }
10215     }
10216   // splitting done. sort intersect point in intersectEdge.
10217   std::vector< std::vector<int> > middle(nDescCell);
10218   int nbOf2DCellsToBeSplit(0);
10219   bool middleNeedsToBeUsed(false);
10220   std::vector<bool> cells2DToTreat(nDescCell,false);
10221   for(int i=0;i<nDescCell;i++)
10222     {
10223       std::vector<int>& isect(intersectEdge[i]);
10224       int sz((int)isect.size());
10225       if(sz>1)
10226         {
10227           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10228           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10229           e->sortSubNodesAbs(coords,isect);
10230           e->decrRef();
10231         }
10232       if(sz!=0)
10233         {
10234           int idx0(rdi[i]),idx1(rdi[i+1]);
10235           if(idx1-idx0!=1)
10236             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10237           if(!cells2DToTreat[rd[idx0]])
10238             {
10239               cells2DToTreat[rd[idx0]]=true;
10240               nbOf2DCellsToBeSplit++;
10241             }
10242           // try to reuse at most eventual 'middle' of SEG3
10243           std::vector<int>& mid(middle[i]);
10244           mid.resize(sz+1,-1);
10245           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10246             {
10247               middleNeedsToBeUsed=true;
10248               const std::vector<int>& candidates(overlapEdge[i]);
10249               std::vector<int> trueCandidates;
10250               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10251                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10252                   trueCandidates.push_back(*itc);
10253               int stNode(c[ci[i]+1]),endNode(isect[0]);
10254               for(int j=0;j<sz+1;j++)
10255                 {
10256                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10257                     {
10258                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10259                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10260                         { mid[j]=*itc; break; }
10261                     }
10262                   stNode=endNode;
10263                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10264                 }
10265             }
10266         }
10267     }
10268   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10269   if(nbOf2DCellsToBeSplit==0)
10270     return ret.retn();
10271   //
10272   int *retPtr(ret->getPointer());
10273   for(int i=0;i<nCell;i++)
10274     if(cells2DToTreat[i])
10275       *retPtr++=i;
10276   //
10277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10278   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10279   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10280   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10281   if(middleNeedsToBeUsed)
10282     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10283   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10284   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10285   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.
10286   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10287   {
10288     bool areNodesMerged; int newNbOfNodes;
10289     if(nbOfNodesCreated!=0)
10290       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10291   }
10292   return ret.retn();
10293 }
10294
10295 /*!
10296  * 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.
10297  * 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).
10298  * 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
10299  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10300  * 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
10301  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10302  *
10303  * 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
10304  * using new instance, idem for coordinates.
10305  *
10306  * 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.
10307  * 
10308  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10309  *
10310  * \throw If \a this is not coherent.
10311  * \throw If \a this has not spaceDim equal to 2.
10312  * \throw If \a this has not meshDim equal to 2.
10313  * 
10314  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10315  */
10316 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10317 {
10318   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10319   checkCoherency();
10320   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10321     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10322   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10323   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10324   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10325   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10326   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10327   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10328   const double *coords(_coords->begin());
10329   int *newciptr(newci->getPointer());
10330   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10331     {
10332       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10333         ret->pushBackSilent(i);
10334       newciptr[1]=newc->getNumberOfTuples();
10335     }
10336   //
10337   if(ret->empty())
10338     return ret.retn();
10339   if(!appendedCoords->empty())
10340     {
10341       appendedCoords->rearrange(2);
10342       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10343       //non const part
10344       setCoords(newCoords);
10345     }
10346   //non const part
10347   setConnectivity(newc,newci,true);
10348   return ret.retn();
10349 }
10350
10351 /*!
10352  * \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.
10353  *                               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.
10354  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10355  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10356  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10357  * \param [out] addCoo - nodes to be append at the end
10358  * \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.
10359  */
10360 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10361                                          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)
10362 {
10363   static const int SPACEDIM=2;
10364   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10365   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10366   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10367   // Build BB tree of all edges in the tool mesh (second mesh)
10368   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10369   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10370   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10371   intersectEdge1.resize(nDescCell1);
10372   colinear2.resize(nDescCell2);
10373   subDiv2.resize(nDescCell2);
10374   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10375
10376   std::vector<int> candidates1(1);
10377   int offset1(m1Desc->getNumberOfNodes());
10378   int offset2(offset1+m2Desc->getNumberOfNodes());
10379   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10380     {
10381       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10382       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10383       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10384         {
10385           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10386           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10387           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10388           candidates1[0]=i;
10389           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10390           // 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
10391           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10392           std::set<INTERP_KERNEL::Node *> nodes;
10393           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10394           std::size_t szz(nodes.size());
10395           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10396           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10397           for(std::size_t iii=0;iii<szz;iii++,itt++)
10398             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10399           // end of protection
10400           // Performs egde cutting:
10401           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10402           delete pol2;
10403           delete pol1;
10404         }
10405       else
10406         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10407         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10408     }
10409 }
10410
10411 /*!
10412  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10413  * It builds the descending connectivity of the two meshes, and then using a binary tree
10414  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10415  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10416  */
10417 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10418                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10419                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10420                                                    std::vector<double>& addCoo,
10421                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10422 {
10423   // Build desc connectivity
10424   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10425   desc2=DataArrayInt::New();
10426   descIndx2=DataArrayInt::New();
10427   revDesc2=DataArrayInt::New();
10428   revDescIndx2=DataArrayInt::New();
10429   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10430   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10431   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10432   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10433   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10434   std::map<int,int> notUsedMap;
10435   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10436   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10437   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10438 }
10439
10440 /*!
10441  * This method performs the 2nd step of Partition of 2D mesh.
10442  * This method has 4 inputs :
10443  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10444  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10445  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10446  * 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'
10447  * Nodes end up lying consecutively on a cutted edge.
10448  * \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.
10449  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10450  * \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.
10451  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10452  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10453  */
10454 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10455                                            const std::vector<double>& addCoo,
10456                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10457 {
10458   int offset1=m1->getNumberOfNodes();
10459   int ncell=m2->getNumberOfCells();
10460   const int *c=m2->getNodalConnectivity()->getConstPointer();
10461   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10462   const double *coo=m2->getCoords()->getConstPointer();
10463   const double *cooBis=m1->getCoords()->getConstPointer();
10464   int offset2=offset1+m2->getNumberOfNodes();
10465   intersectEdge.resize(ncell);
10466   for(int i=0;i<ncell;i++,cI++)
10467     {
10468       const std::vector<int>& divs=subDiv[i];
10469       int nnode=cI[1]-cI[0]-1;
10470       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10471       std::map<INTERP_KERNEL::Node *, int> mapp22;
10472       for(int j=0;j<nnode;j++)
10473         {
10474           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10475           int nnid=c[(*cI)+j+1];
10476           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10477           mapp22[nn]=nnid+offset1;
10478         }
10479       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10480       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10481         ((*it).second.first)->decrRef();
10482       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10483       std::map<INTERP_KERNEL::Node *,int> mapp3;
10484       for(std::size_t j=0;j<divs.size();j++)
10485         {
10486           int id=divs[j];
10487           INTERP_KERNEL::Node *tmp=0;
10488           if(id<offset1)
10489             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10490           else if(id<offset2)
10491             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10492           else
10493             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10494           addNodes[j]=tmp;
10495           mapp3[tmp]=id;
10496         }
10497       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10498       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10499         (*it)->decrRef();
10500       e->decrRef();
10501     }
10502 }
10503
10504 /*!
10505  * 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).
10506  * 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
10507  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10508  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10509  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10510  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10511  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10512  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10513  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10514  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10515  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10516  * \param [out] cut3DSuf input/output param.
10517  */
10518 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10519                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10520                                                    const int *desc, const int *descIndx, 
10521                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10522 {
10523   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10524   int nbOf3DSurfCell=(int)cut3DSurf.size();
10525   for(int i=0;i<nbOf3DSurfCell;i++)
10526     {
10527       std::vector<int> res;
10528       int offset=descIndx[i];
10529       int nbOfSeg=descIndx[i+1]-offset;
10530       for(int j=0;j<nbOfSeg;j++)
10531         {
10532           int edgeId=desc[offset+j];
10533           int status=cut3DCurve[edgeId];
10534           if(status!=-2)
10535             {
10536               if(status>-1)
10537                 res.push_back(status);
10538               else
10539                 {
10540                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10541                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10542                 }
10543             }
10544         }
10545       switch(res.size())
10546       {
10547         case 2:
10548           {
10549             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10550             break;
10551           }
10552         case 1:
10553         case 0:
10554           {
10555             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10556             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10557             if(res.size()==2)
10558               {
10559                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10560               }
10561             else
10562               {
10563                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10564               }
10565             break;
10566           }
10567         default:
10568           {// case when plane is on a multi colinear edge of a polyhedron
10569             if((int)res.size()==2*nbOfSeg)
10570               {
10571                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10572               }
10573             else
10574               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10575           }
10576       }
10577     }
10578 }
10579
10580 /*!
10581  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10582  * 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).
10583  * 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
10584  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10585  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10586  * \param desc is the descending connectivity 3D->3DSurf
10587  * \param descIndx is the descending connectivity index 3D->3DSurf
10588  */
10589 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10590                                                   const int *desc, const int *descIndx,
10591                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10592 {
10593   checkFullyDefined();
10594   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10595     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10596   const int *nodal3D=_nodal_connec->getConstPointer();
10597   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10598   int nbOfCells=getNumberOfCells();
10599   for(int i=0;i<nbOfCells;i++)
10600     {
10601       std::map<int, std::set<int> > m;
10602       int offset=descIndx[i];
10603       int nbOfFaces=descIndx[i+1]-offset;
10604       int start=-1;
10605       int end=-1;
10606       for(int j=0;j<nbOfFaces;j++)
10607         {
10608           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10609           if(p.first!=-1 && p.second!=-1)
10610             {
10611               if(p.first!=-2)
10612                 {
10613                   start=p.first; end=p.second;
10614                   m[p.first].insert(p.second);
10615                   m[p.second].insert(p.first);
10616                 }
10617               else
10618                 {
10619                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10620                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10621                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10622                   INTERP_KERNEL::NormalizedCellType cmsId;
10623                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10624                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10625                   for(unsigned k=0;k<nbOfNodesSon;k++)
10626                     {
10627                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10628                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10629                     }
10630                 }
10631             }
10632         }
10633       if(m.empty())
10634         continue;
10635       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10636       int prev=end;
10637       while(end!=start)
10638         {
10639           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10640           const std::set<int>& s=(*it).second;
10641           std::set<int> s2; s2.insert(prev);
10642           std::set<int> s3;
10643           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10644           if(s3.size()==1)
10645             {
10646               int val=*s3.begin();
10647               conn.push_back(start);
10648               prev=start;
10649               start=val;
10650             }
10651           else
10652             start=end;
10653         }
10654       conn.push_back(end);
10655       if(conn.size()>3)
10656         {
10657           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10658           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10659           cellIds->pushBackSilent(i);
10660         }
10661     }
10662 }
10663
10664 /*!
10665  * 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
10666  * 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
10667  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10668  * 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
10669  * 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.
10670  * 
10671  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10672  */
10673 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10674 {
10675   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10676   if(sz>=4)
10677     {
10678       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10679       if(cm.getDimension()==2)
10680         {
10681           const int *node=nodalConnBg+1;
10682           int startNode=*node++;
10683           double refX=coords[2*startNode];
10684           for(;node!=nodalConnEnd;node++)
10685             {
10686               if(coords[2*(*node)]<refX)
10687                 {
10688                   startNode=*node;
10689                   refX=coords[2*startNode];
10690                 }
10691             }
10692           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10693           refX=1e300;
10694           double tmp1;
10695           double tmp2[2];
10696           double angle0=-M_PI/2;
10697           //
10698           int nextNode=-1;
10699           int prevNode=-1;
10700           double resRef;
10701           double angleNext=0.;
10702           while(nextNode!=startNode)
10703             {
10704               nextNode=-1;
10705               resRef=1e300;
10706               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10707                 {
10708                   if(*node!=tmpOut.back() && *node!=prevNode)
10709                     {
10710                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10711                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10712                       double res;
10713                       if(angleM<=angle0)
10714                         res=angle0-angleM;
10715                       else
10716                         res=angle0-angleM+2.*M_PI;
10717                       if(res<resRef)
10718                         {
10719                           nextNode=*node;
10720                           resRef=res;
10721                           angleNext=angleM;
10722                         }
10723                     }
10724                 }
10725               if(nextNode!=startNode)
10726                 {
10727                   angle0=angleNext-M_PI;
10728                   if(angle0<-M_PI)
10729                     angle0+=2*M_PI;
10730                   prevNode=tmpOut.back();
10731                   tmpOut.push_back(nextNode);
10732                 }
10733             }
10734           std::vector<int> tmp3(2*(sz-1));
10735           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10736           std::copy(nodalConnBg+1,nodalConnEnd,it);
10737           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10738             {
10739               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10740               return false;
10741             }
10742           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10743             {
10744               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10745               return false;
10746             }
10747           else
10748             {
10749               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10750               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10751               return true;
10752             }
10753         }
10754       else
10755         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10756     }
10757   else
10758     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10759 }
10760
10761 /*!
10762  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10763  * 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.
10764  * 
10765  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10766  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10767  * \param [in,out] arr array in which the remove operation will be done.
10768  * \param [in,out] arrIndx array in the remove operation will modify
10769  * \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])
10770  * \return true if \b arr and \b arrIndx have been modified, false if not.
10771  */
10772 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10773 {
10774   if(!arrIndx || !arr)
10775     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10776   if(offsetForRemoval<0)
10777     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10778   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10779   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10780   int *arrIPtr=arrIndx->getPointer();
10781   *arrIPtr++=0;
10782   int previousArrI=0;
10783   const int *arrPtr=arr->getConstPointer();
10784   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10785   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10786     {
10787       if(*arrIPtr-previousArrI>offsetForRemoval)
10788         {
10789           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10790             {
10791               if(s.find(*work)==s.end())
10792                 arrOut.push_back(*work);
10793             }
10794         }
10795       previousArrI=*arrIPtr;
10796       *arrIPtr=(int)arrOut.size();
10797     }
10798   if(arr->getNumberOfTuples()==(int)arrOut.size())
10799     return false;
10800   arr->alloc((int)arrOut.size(),1);
10801   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10802   return true;
10803 }
10804
10805 /*!
10806  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10807  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10808  * The selection of extraction is done standardly in new2old format.
10809  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10810  *
10811  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10812  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10813  * \param [in] arrIn arr origin array from which the extraction will be done.
10814  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10815  * \param [out] arrOut the resulting array
10816  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10817  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10818  */
10819 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10820                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10821 {
10822   if(!arrIn || !arrIndxIn)
10823     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10824   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10825   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10826     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10827   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10828   const int *arrInPtr=arrIn->getConstPointer();
10829   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10830   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10831   if(nbOfGrps<0)
10832     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10833   int maxSizeOfArr=arrIn->getNumberOfTuples();
10834   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10835   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10836   arrIo->alloc((int)(sz+1),1);
10837   const int *idsIt=idsOfSelectBg;
10838   int *work=arrIo->getPointer();
10839   *work++=0;
10840   int lgth=0;
10841   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10842     {
10843       if(*idsIt>=0 && *idsIt<nbOfGrps)
10844         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10845       else
10846         {
10847           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10848           throw INTERP_KERNEL::Exception(oss.str().c_str());
10849         }
10850       if(lgth>=work[-1])
10851         *work=lgth;
10852       else
10853         {
10854           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10855           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10856           throw INTERP_KERNEL::Exception(oss.str().c_str());
10857         }
10858     }
10859   arro->alloc(lgth,1);
10860   work=arro->getPointer();
10861   idsIt=idsOfSelectBg;
10862   for(std::size_t i=0;i<sz;i++,idsIt++)
10863     {
10864       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10865         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10866       else
10867         {
10868           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10869           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10870           throw INTERP_KERNEL::Exception(oss.str().c_str());
10871         }
10872     }
10873   arrOut=arro.retn();
10874   arrIndexOut=arrIo.retn();
10875 }
10876
10877 /*!
10878  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10879  * 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 ).
10880  * The selection of extraction is done standardly in new2old format.
10881  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10882  *
10883  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10884  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10885  * \param [in] arrIn arr origin array from which the extraction will be done.
10886  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10887  * \param [out] arrOut the resulting array
10888  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10889  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10890  */
10891 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10892                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10893 {
10894   if(!arrIn || !arrIndxIn)
10895     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10896   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10897   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10898     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10899   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10900   const int *arrInPtr=arrIn->getConstPointer();
10901   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10902   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10903   if(nbOfGrps<0)
10904     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10905   int maxSizeOfArr=arrIn->getNumberOfTuples();
10906   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10907   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10908   arrIo->alloc((int)(sz+1),1);
10909   int idsIt=idsOfSelectStart;
10910   int *work=arrIo->getPointer();
10911   *work++=0;
10912   int lgth=0;
10913   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10914     {
10915       if(idsIt>=0 && idsIt<nbOfGrps)
10916         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10917       else
10918         {
10919           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10920           throw INTERP_KERNEL::Exception(oss.str().c_str());
10921         }
10922       if(lgth>=work[-1])
10923         *work=lgth;
10924       else
10925         {
10926           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10927           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10928           throw INTERP_KERNEL::Exception(oss.str().c_str());
10929         }
10930     }
10931   arro->alloc(lgth,1);
10932   work=arro->getPointer();
10933   idsIt=idsOfSelectStart;
10934   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10935     {
10936       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10937         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10938       else
10939         {
10940           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10941           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10942           throw INTERP_KERNEL::Exception(oss.str().c_str());
10943         }
10944     }
10945   arrOut=arro.retn();
10946   arrIndexOut=arrIo.retn();
10947 }
10948
10949 /*!
10950  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10951  * 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
10952  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10953  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10954  *
10955  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10956  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10957  * \param [in] arrIn arr origin array from which the extraction will be done.
10958  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10959  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10960  * \param [in] srcArrIndex index array of \b srcArr
10961  * \param [out] arrOut the resulting array
10962  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10963  * 
10964  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10965  */
10966 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10967                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10968                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10969 {
10970   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10971     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10972   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10973   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10974   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10975   std::vector<bool> v(nbOfTuples,true);
10976   int offset=0;
10977   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10978   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10979   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10980     {
10981       if(*it>=0 && *it<nbOfTuples)
10982         {
10983           v[*it]=false;
10984           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10985         }
10986       else
10987         {
10988           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10989           throw INTERP_KERNEL::Exception(oss.str().c_str());
10990         }
10991     }
10992   srcArrIndexPtr=srcArrIndex->getConstPointer();
10993   arrIo->alloc(nbOfTuples+1,1);
10994   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10995   const int *arrInPtr=arrIn->getConstPointer();
10996   const int *srcArrPtr=srcArr->getConstPointer();
10997   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10998   int *arroPtr=arro->getPointer();
10999   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11000     {
11001       if(v[ii])
11002         {
11003           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11004           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11005         }
11006       else
11007         {
11008           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
11009           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11010           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11011         }
11012     }
11013   arrOut=arro.retn();
11014   arrIndexOut=arrIo.retn();
11015 }
11016
11017 /*!
11018  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11019  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11020  *
11021  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
11022  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
11023  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11024  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11025  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
11026  * \param [in] srcArrIndex index array of \b srcArr
11027  * 
11028  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
11029  */
11030 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11031                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11032 {
11033   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11034     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
11035   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11036   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11037   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11038   int *arrInOutPtr=arrInOut->getPointer();
11039   const int *srcArrPtr=srcArr->getConstPointer();
11040   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11041     {
11042       if(*it>=0 && *it<nbOfTuples)
11043         {
11044           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11045             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11046           else
11047             {
11048               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] !";
11049               throw INTERP_KERNEL::Exception(oss.str().c_str());
11050             }
11051         }
11052       else
11053         {
11054           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11055           throw INTERP_KERNEL::Exception(oss.str().c_str());
11056         }
11057     }
11058 }
11059
11060 /*!
11061  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11062  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11063  * 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]].
11064  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11065  * A negative value in \b arrIn means that it is ignored.
11066  * 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.
11067  * 
11068  * \param [in] arrIn arr origin array from which the extraction will be done.
11069  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11070  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11071  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11072  */
11073 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11074 {
11075   int seed=0,nbOfDepthPeelingPerformed=0;
11076   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11077 }
11078
11079 /*!
11080  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11081  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11082  * 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]].
11083  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11084  * A negative value in \b arrIn means that it is ignored.
11085  * 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.
11086  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11087  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11088  * \param [in] arrIn arr origin array from which the extraction will be done.
11089  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11090  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11091  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11092  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11093  * \sa MEDCouplingUMesh::partitionBySpreadZone
11094  */
11095 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11096 {
11097   nbOfDepthPeelingPerformed=0;
11098   if(!arrIndxIn)
11099     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11100   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11101   if(nbOfTuples<=0)
11102     {
11103       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11104       return ret;
11105     }
11106   //
11107   std::vector<bool> fetched(nbOfTuples,false);
11108   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11109 }
11110
11111 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11112 {
11113   nbOfDepthPeelingPerformed=0;
11114   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11115     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11116   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11117   std::vector<bool> fetched2(nbOfTuples,false);
11118   int i=0;
11119   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11120     {
11121       if(*seedElt>=0 && *seedElt<nbOfTuples)
11122         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11123       else
11124         { 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()); }
11125     }
11126   const int *arrInPtr=arrIn->getConstPointer();
11127   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11128   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11129   std::vector<int> idsToFetch1(seedBg,seedEnd);
11130   std::vector<int> idsToFetch2;
11131   std::vector<int> *idsToFetch=&idsToFetch1;
11132   std::vector<int> *idsToFetchOther=&idsToFetch2;
11133   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11134     {
11135       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11136         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11137           if(!fetched[*it2])
11138             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11139       std::swap(idsToFetch,idsToFetchOther);
11140       idsToFetchOther->clear();
11141       nbOfDepthPeelingPerformed++;
11142     }
11143   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11144   i=0;
11145   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11146   int *retPtr=ret->getPointer();
11147   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11148     if(*it)
11149       *retPtr++=i;
11150   return ret.retn();
11151 }
11152
11153 /*!
11154  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11155  * 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
11156  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11157  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11158  *
11159  * \param [in] start begin of set of ids of the input extraction (included)
11160  * \param [in] end end of set of ids of the input extraction (excluded)
11161  * \param [in] step step of the set of ids in range mode.
11162  * \param [in] arrIn arr origin array from which the extraction will be done.
11163  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11164  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11165  * \param [in] srcArrIndex index array of \b srcArr
11166  * \param [out] arrOut the resulting array
11167  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11168  * 
11169  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11170  */
11171 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11172                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11173                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11174 {
11175   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11176     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11177   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11178   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11179   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11180   int offset=0;
11181   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11182   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11183   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11184   int it=start;
11185   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11186     {
11187       if(it>=0 && it<nbOfTuples)
11188         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11189       else
11190         {
11191           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11192           throw INTERP_KERNEL::Exception(oss.str().c_str());
11193         }
11194     }
11195   srcArrIndexPtr=srcArrIndex->getConstPointer();
11196   arrIo->alloc(nbOfTuples+1,1);
11197   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11198   const int *arrInPtr=arrIn->getConstPointer();
11199   const int *srcArrPtr=srcArr->getConstPointer();
11200   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11201   int *arroPtr=arro->getPointer();
11202   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11203     {
11204       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11205       if(pos<0)
11206         {
11207           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11208           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11209         }
11210       else
11211         {
11212           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11213           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11214         }
11215     }
11216   arrOut=arro.retn();
11217   arrIndexOut=arrIo.retn();
11218 }
11219
11220 /*!
11221  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11222  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11223  *
11224  * \param [in] start begin of set of ids of the input extraction (included)
11225  * \param [in] end end of set of ids of the input extraction (excluded)
11226  * \param [in] step step of the set of ids in range mode.
11227  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11228  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11229  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11230  * \param [in] srcArrIndex index array of \b srcArr
11231  * 
11232  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11233  */
11234 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11235                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11236 {
11237   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11238     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11239   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11240   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11241   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11242   int *arrInOutPtr=arrInOut->getPointer();
11243   const int *srcArrPtr=srcArr->getConstPointer();
11244   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11245   int it=start;
11246   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11247     {
11248       if(it>=0 && it<nbOfTuples)
11249         {
11250           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11251             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11252           else
11253             {
11254               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11255               throw INTERP_KERNEL::Exception(oss.str().c_str());
11256             }
11257         }
11258       else
11259         {
11260           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11261           throw INTERP_KERNEL::Exception(oss.str().c_str());
11262         }
11263     }
11264 }
11265
11266 /*!
11267  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11268  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11269  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11270  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11271  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11272  * 
11273  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11274  */
11275 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11276 {
11277   checkFullyDefined();
11278   int mdim=getMeshDimension();
11279   int spaceDim=getSpaceDimension();
11280   if(mdim!=spaceDim)
11281     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11282   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11283   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11284   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11285   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11286   ret->setCoords(getCoords());
11287   ret->allocateCells((int)partition.size());
11288   //
11289   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11290     {
11291       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11292       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11293       switch(mdim)
11294       {
11295         case 2:
11296           cell=tmp->buildUnionOf2DMesh();
11297           break;
11298         case 3:
11299           cell=tmp->buildUnionOf3DMesh();
11300           break;
11301         default:
11302           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11303       }
11304
11305       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11306     }
11307   //
11308   ret->finishInsertingCells();
11309   return ret.retn();
11310 }
11311
11312 /*!
11313  * This method partitions \b this into contiguous zone.
11314  * This method only needs a well defined connectivity. Coordinates are not considered here.
11315  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11316  */
11317 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11318 {
11319   int nbOfCellsCur=getNumberOfCells();
11320   std::vector<DataArrayInt *> ret;
11321   if(nbOfCellsCur<=0)
11322     return ret;
11323   DataArrayInt *neigh=0,*neighI=0;
11324   computeNeighborsOfCells(neigh,neighI);
11325   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11326   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11327   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11328   int seed=0;
11329   while(seed<nbOfCellsCur)
11330     {
11331       int nbOfPeelPerformed=0;
11332       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11333       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11334     }
11335   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11336     ret.push_back((*it).retn());
11337   return ret;
11338 }
11339
11340 /*!
11341  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11342  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11343  *
11344  * \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.
11345  * \return a newly allocated DataArrayInt to be managed by the caller.
11346  * \throw In case of \a code has not the right format (typically of size 3*n)
11347  */
11348 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11349 {
11350   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11351   std::size_t nb=code.size()/3;
11352   if(code.size()%3!=0)
11353     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11354   ret->alloc((int)nb,2);
11355   int *retPtr=ret->getPointer();
11356   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11357     {
11358       retPtr[0]=code[3*i+2];
11359       retPtr[1]=code[3*i+2]+code[3*i+1];
11360     }
11361   return ret.retn();
11362 }
11363
11364 /*!
11365  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11366  * All cells in \a this are expected to be linear 3D cells.
11367  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11368  * It leads to an increase to number of cells.
11369  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11370  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11371  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11372  *
11373  * \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.
11374  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11375  * \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. 
11376  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11377  *          an id of old cell producing it. The caller is to delete this array using
11378  *         decrRef() as it is no more needed.
11379  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11380  *
11381  * \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
11382  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11383  * 
11384  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11385  * \throw If \a this is not fully constituted with linear 3D cells.
11386  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11387  */
11388 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11389 {
11390   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11391   checkConnectivityFullyDefined();
11392   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11393     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11394   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11395   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11397   int *retPt(ret->getPointer());
11398   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11399   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11400   const int *oldc(_nodal_connec->begin());
11401   const int *oldci(_nodal_connec_index->begin());
11402   const double *coords(_coords->begin());
11403   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11404     {
11405       std::vector<int> a; std::vector<double> b;
11406       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11407       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11408       const int *aa(&a[0]);
11409       if(!b.empty())
11410         {
11411           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11412             if(*it<0)
11413               *it=(-(*(it))-1+nbNodes);
11414           addPts->insertAtTheEnd(b.begin(),b.end());
11415           nbNodes+=(int)b.size()/3;
11416         }
11417       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11418         newConn->insertAtTheEnd(aa,aa+4);
11419     }
11420   if(!addPts->empty())
11421     {
11422       addPts->rearrange(3);
11423       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11424       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11425       ret0->setCoords(addPts);
11426     }
11427   else
11428     {
11429       nbOfAdditionalPoints=0;
11430       ret0->setCoords(getCoords());
11431     }
11432   ret0->setNodalConnectivity(newConn);
11433   //
11434   ret->computeOffsets2();
11435   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11436   return ret0.retn();
11437 }
11438
11439 /*!
11440  * 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). 
11441  *
11442  * \sa MEDCouplingUMesh::split2DCells
11443  */
11444 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11445 {
11446   checkConnectivityFullyDefined();
11447   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11448   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11449   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11450   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11451   int prevPosOfCi(ciPtr[0]);
11452   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11453     {
11454       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11455       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11456       for(int j=0;j<sz;j++)
11457         {
11458           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11459           for(int k=0;k<sz2;k++)
11460             *cPtr++=subPtr[offset2+k];
11461           if(j!=sz-1)
11462             *cPtr++=oldConn[prevPosOfCi+j+2];
11463           deltaSz+=sz2;
11464         }
11465       prevPosOfCi=ciPtr[1];
11466       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11467     }
11468   if(c->end()!=cPtr)
11469     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11470   _nodal_connec->decrRef();
11471   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11472 }
11473
11474 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11475 {
11476   if(id!=-1)
11477     return id;
11478   else
11479     {
11480       int ret(nodesCnter++);
11481       double newPt[2];
11482       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11483       addCoo.insertAtTheEnd(newPt,newPt+2);
11484       return ret;
11485     }
11486 }
11487
11488 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11489 {
11490   if(id!=-1)
11491     return id;
11492   else
11493     {
11494       int ret(nodesCnter++);
11495       double newPt[2];
11496       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11497       addCoo.insertAtTheEnd(newPt,newPt+2);
11498       return ret;
11499     }
11500 }
11501
11502
11503 /// @cond INTERNAL
11504
11505 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)
11506 {
11507   int tmp[3];
11508   int trueStart(start>=0?start:nbOfEdges+start);
11509   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11510   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11511   if(linOrArc)
11512     {
11513       if(stp-start>1)
11514         {
11515           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11516           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11517           middles.push_back(tmp3+offset);
11518         }
11519       else
11520         middles.push_back(connBg[trueStart+nbOfEdges]);
11521     }
11522 }
11523
11524 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)
11525 {
11526   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11527   newConnOfCell->pushBackSilent(tmpEnd);
11528   if(linOrArc)
11529     {
11530       if(stp-start>1)
11531         {
11532           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11533           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11534           middles.push_back(tmp3+offset);
11535         }
11536       else
11537         middles.push_back(connBg[start+nbOfEdges]);
11538     }
11539 }
11540
11541 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)
11542 {
11543   // only the quadratic point to deal with:
11544   if(linOrArc)
11545     {
11546       if(stp-start>1)
11547         {
11548           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11549           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11550           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11551           middles.push_back(tmp3+offset);
11552         }
11553       else
11554         middles.push_back(connBg[start+nbOfEdges]);
11555     }
11556 }
11557
11558 /// @cond INTERNAL
11559
11560 /*!
11561  * 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 ) .
11562  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11563  */
11564 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11565 {
11566   std::size_t sz(std::distance(connBg,connEnd));
11567   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11568     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11569   sz--;
11570   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11571   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11572   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11573   unsigned nbOfHit(0); // number of fusions operated
11574   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11575   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
11576   INTERP_KERNEL::NormalizedCellType typeOfSon;
11577   std::vector<int> middles;
11578   bool ret(false);
11579   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11580     {
11581       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11582       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11583       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11584       posEndElt = posBaseElt+1;
11585
11586       // Look backward first: are the final edges of the cells colinear with the first ones?
11587       // This initializes posBaseElt.
11588       if(nbOfTurn==0)
11589         {
11590           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11591             {
11592               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11593               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11594               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11595               bool isColinear=eint->areColinears();
11596               if(isColinear)
11597                 {
11598                   nbOfHit++;
11599                   posBaseElt--;
11600                   ret=true;
11601                 }
11602               delete eint;
11603               eCand->decrRef();
11604               if(!isColinear)
11605                 break;
11606             }
11607         }
11608       // Now move forward:
11609       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11610       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11611         {
11612           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11613           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11614           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11615           bool isColinear(eint->areColinears());
11616           if(isColinear)
11617             {
11618               nbOfHit++;
11619               posEndElt++;
11620               ret=true;
11621             }
11622           delete eint;
11623           eCand->decrRef();
11624           if(!isColinear)
11625               break;
11626         }
11627       //push [posBaseElt,posEndElt) in newConnOfCell using e
11628       // 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!
11629       if(nbOfTurn==0)
11630         // at the begining of the connectivity (insert type)
11631         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11632       else if((nbOfHit+nbOfTurn) != (nbs-1))
11633         // in the middle
11634         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11635       if ((nbOfHit+nbOfTurn) == (nbs-1))
11636         // at the end (only quad points to deal with)
11637         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11638       posBaseElt=posEndElt;
11639       e->decrRef();
11640     }
11641   if(!middles.empty())
11642     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11643   return ret;
11644 }
11645
11646 /*!
11647  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11648  *
11649  * \return  int - the number of new nodes created.
11650  * \sa MEDCouplingUMesh::split2DCells
11651  */
11652 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11653 {
11654   checkCoherency();
11655   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11656   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11657   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11658   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11659   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11660   const double *oldCoordsPtr(getCoords()->begin());
11661   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11662   int prevPosOfCi(ciPtr[0]);
11663   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11664     {
11665       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11666       for(int j=0;j<sz;j++)
11667         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11668       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11669       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11670         {
11671           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11672           if(sz2==0)
11673             {
11674               if(j<sz-1)
11675                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11676               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11677               continue;
11678             }
11679           std::vector<INTERP_KERNEL::Node *> ns(3);
11680           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11681           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11682           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11683           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11684           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11685             {
11686               cPtr[1]=subPtr[offset2+k];
11687               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11688             }
11689           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11690           if(j!=sz-1)
11691             { cPtr[1]=tmpEnd; }
11692           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11693         }
11694       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11695       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11696     }
11697   if(c->end()!=cPtr)
11698     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11699   _nodal_connec->decrRef();
11700   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11701   addCoo->rearrange(2);
11702   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11703   setCoords(coo);
11704   return addCoo->getNumberOfTuples();
11705 }
11706
11707 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11708 {
11709   if(nodalConnec && nodalConnecIndex)
11710     {
11711       types.clear();
11712       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11713       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11714       if(nbOfElem>0)
11715         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11716           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11717     }
11718 }
11719
11720 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11721     _own_cell(true),_cell_id(-1),_nb_cell(0)
11722 {
11723   if(mesh)
11724     {
11725       mesh->incrRef();
11726       _nb_cell=mesh->getNumberOfCells();
11727     }
11728 }
11729
11730 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11731 {
11732   if(_mesh)
11733     _mesh->decrRef();
11734   if(_own_cell)
11735     delete _cell;
11736 }
11737
11738 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11739     _own_cell(false),_cell_id(bg-1),
11740     _nb_cell(end)
11741 {
11742   if(mesh)
11743     mesh->incrRef();
11744 }
11745
11746 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11747 {
11748   _cell_id++;
11749   if(_cell_id<_nb_cell)
11750     {
11751       _cell->next();
11752       return _cell;
11753     }
11754   else
11755     return 0;
11756 }
11757
11758 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11759 {
11760   if(_mesh)
11761     _mesh->incrRef();
11762 }
11763
11764 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11765 {
11766   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11767 }
11768
11769 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11770 {
11771   if(_mesh)
11772     _mesh->decrRef();
11773 }
11774
11775 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11776     _itc(itc),
11777     _bg(bg),_end(end)
11778 {
11779   if(_mesh)
11780     _mesh->incrRef();
11781 }
11782
11783 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11784 {
11785   if(_mesh)
11786     _mesh->decrRef();
11787 }
11788
11789 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11790 {
11791   return _type;
11792 }
11793
11794 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11795 {
11796   return _end-_bg;
11797 }
11798
11799 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11800 {
11801   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11802 }
11803
11804 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11805 {
11806   if(mesh)
11807     {
11808       mesh->incrRef();
11809       _nb_cell=mesh->getNumberOfCells();
11810     }
11811 }
11812
11813 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11814 {
11815   if(_mesh)
11816     _mesh->decrRef();
11817   delete _cell;
11818 }
11819
11820 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11821 {
11822   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11823   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11824   if(_cell_id<_nb_cell)
11825     {
11826       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11827       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11828       int startId=_cell_id;
11829       _cell_id+=nbOfElems;
11830       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11831     }
11832   else
11833     return 0;
11834 }
11835
11836 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11837 {
11838   if(mesh)
11839     {
11840       _conn=mesh->getNodalConnectivity()->getPointer();
11841       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11842     }
11843 }
11844
11845 void MEDCouplingUMeshCell::next()
11846 {
11847   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11848     {
11849       _conn+=_conn_lgth;
11850       _conn_indx++;
11851     }
11852   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11853 }
11854
11855 std::string MEDCouplingUMeshCell::repr() const
11856 {
11857   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11858     {
11859       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11860       oss << " : ";
11861       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11862       return oss.str();
11863     }
11864   else
11865     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11866 }
11867
11868 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11869 {
11870   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11871     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11872   else
11873     return INTERP_KERNEL::NORM_ERROR;
11874 }
11875
11876 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11877 {
11878   lgth=_conn_lgth;
11879   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11880     return _conn;
11881   else
11882     return 0;
11883 }