Salome HOME
medcalc and commands history
[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. Closer is the estimation to the number of cells effectively inserted,
320  * less will be the needs to realloc. 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 \b this. The data array returned has to be dealt by the caller.
1400  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1401  * the format of 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 find in \b this cells 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 cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2334  * This method method returns 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 cells ids in \b this containg s0 in above algorithm.
2343  * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get 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   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2470   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2471   DataArrayInt *idsTmp=0;
2472   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2473   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2474   if(!b)
2475     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2476   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2477   DataArrayInt *tmp0=0,*tmp1=0;
2478   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2479   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2480   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2481   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2482   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2483   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2484   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2485   //
2486   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2487   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2488   nodeIdsToDuplicate=s3.retn();
2489 }
2490
2491 /*!
2492  * This method operates a modification of the connectivity and coords in \b this.
2493  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2494  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2495  * 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
2496  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2497  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2498  * 
2499  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2500  * 
2501  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2502  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2503  */
2504 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2505 {
2506   int nbOfNodes=getNumberOfNodes();
2507   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2508   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2509 }
2510
2511 /*!
2512  * This method renumbers only nodal connectivity in \a this. The renumbering is only an offset applied. So this method is a specialization of
2513  * \a renumberNodesInConn. \b WARNING, this method does not check that the resulting node ids in the nodal connectivity is in a valid range !
2514  *
2515  * \param [in] offset - specifies the offset to be applied on each element of connectivity.
2516  *
2517  * \sa renumberNodesInConn
2518  */
2519 void MEDCouplingUMesh::renumberNodesWithOffsetInConn(int offset)
2520 {
2521   checkConnectivityFullyDefined();
2522   int *conn(getNodalConnectivity()->getPointer());
2523   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2524   int nbOfCells(getNumberOfCells());
2525   for(int i=0;i<nbOfCells;i++)
2526     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2527       {
2528         int& node=conn[iconn];
2529         if(node>=0)//avoid polyhedron separator
2530           {
2531             node+=offset;
2532           }
2533       }
2534   _nodal_connec->declareAsNew();
2535   updateTime();
2536 }
2537
2538 /*!
2539  *  Same than renumberNodesInConn(const int *) except that here the format of old-to-new traducer is using map instead
2540  *  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
2541  *  of a big mesh.
2542  */
2543 void MEDCouplingUMesh::renumberNodesInConn(const INTERP_KERNEL::HashMap<int,int>& newNodeNumbersO2N)
2544 {
2545   checkConnectivityFullyDefined();
2546   int *conn(getNodalConnectivity()->getPointer());
2547   const int *connIndex(getNodalConnectivityIndex()->getConstPointer());
2548   int nbOfCells(getNumberOfCells());
2549   for(int i=0;i<nbOfCells;i++)
2550     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2551       {
2552         int& node=conn[iconn];
2553         if(node>=0)//avoid polyhedron separator
2554           {
2555             INTERP_KERNEL::HashMap<int,int>::const_iterator it(newNodeNumbersO2N.find(node));
2556             if(it!=newNodeNumbersO2N.end())
2557               {
2558                 node=(*it).second;
2559               }
2560             else
2561               {
2562                 std::ostringstream oss; oss << "MEDCouplingUMesh::renumberNodesInConn(map) : presence in connectivity for cell #" << i << " of node #" << node << " : Not in map !";
2563                 throw INTERP_KERNEL::Exception(oss.str().c_str());
2564               }
2565           }
2566       }
2567   _nodal_connec->declareAsNew();
2568   updateTime();
2569 }
2570
2571 /*!
2572  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2573  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2574  * This method is a generalization of shiftNodeNumbersInConn().
2575  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2576  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2577  *         this->getNumberOfNodes(), in "Old to New" mode. 
2578  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2579  *  \throw If the nodal connectivity of cells is not defined.
2580  *
2581  *  \if ENABLE_EXAMPLES
2582  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2583  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2584  *  \endif
2585  */
2586 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2587 {
2588   checkConnectivityFullyDefined();
2589   int *conn=getNodalConnectivity()->getPointer();
2590   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2591   int nbOfCells(getNumberOfCells());
2592   for(int i=0;i<nbOfCells;i++)
2593     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2594       {
2595         int& node=conn[iconn];
2596         if(node>=0)//avoid polyhedron separator
2597           {
2598             node=newNodeNumbersO2N[node];
2599           }
2600       }
2601   _nodal_connec->declareAsNew();
2602   updateTime();
2603 }
2604
2605 /*!
2606  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2607  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2608  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2609  * 
2610  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2611  */
2612 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2613 {
2614   checkConnectivityFullyDefined();
2615   int *conn=getNodalConnectivity()->getPointer();
2616   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2617   int nbOfCells=getNumberOfCells();
2618   for(int i=0;i<nbOfCells;i++)
2619     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2620       {
2621         int& node=conn[iconn];
2622         if(node>=0)//avoid polyhedron separator
2623           {
2624             node+=delta;
2625           }
2626       }
2627   _nodal_connec->declareAsNew();
2628   updateTime();
2629 }
2630
2631 /*!
2632  * This method operates a modification of the connectivity in \b this.
2633  * 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.
2634  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2635  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2636  * 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
2637  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2638  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2639  * 
2640  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2641  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2642  * 
2643  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2644  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2645  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2646  */
2647 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2648 {
2649   checkConnectivityFullyDefined();
2650   std::map<int,int> m;
2651   int val=offset;
2652   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2653     m[*work]=val;
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             std::map<int,int>::iterator it=m.find(node);
2664             if(it!=m.end())
2665               node=(*it).second;
2666           }
2667       }
2668   updateTime();
2669 }
2670
2671 /*!
2672  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2673  *
2674  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2675  * After the call of this method the number of cells remains the same as before.
2676  *
2677  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2678  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2679  * be strictly in [0;this->getNumberOfCells()).
2680  *
2681  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2682  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2683  * should be contained in[0;this->getNumberOfCells()).
2684  * 
2685  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2686  */
2687 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2688 {
2689   checkConnectivityFullyDefined();
2690   int nbCells=getNumberOfCells();
2691   const int *array=old2NewBg;
2692   if(check)
2693     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2694   //
2695   const int *conn=_nodal_connec->getConstPointer();
2696   const int *connI=_nodal_connec_index->getConstPointer();
2697   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2698   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2699   const int *n2oPtr=n2o->begin();
2700   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2701   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2702   newConn->copyStringInfoFrom(*_nodal_connec);
2703   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2704   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2705   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2706   //
2707   int *newC=newConn->getPointer();
2708   int *newCI=newConnI->getPointer();
2709   int loc=0;
2710   newCI[0]=loc;
2711   for(int i=0;i<nbCells;i++)
2712     {
2713       int pos=n2oPtr[i];
2714       int nbOfElts=connI[pos+1]-connI[pos];
2715       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2716       loc+=nbOfElts;
2717       newCI[i+1]=loc;
2718     }
2719   //
2720   setConnectivity(newConn,newConnI);
2721   if(check)
2722     free(const_cast<int *>(array));
2723 }
2724
2725 /*!
2726  * Finds cells whose bounding boxes intersect a given bounding box.
2727  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2728  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2729  *         zMax (if in 3D). 
2730  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2731  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2732  *         extent of the bounding box of cell to produce an addition to this bounding box.
2733  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2734  *         cells. The caller is to delete this array using decrRef() as it is no more
2735  *         needed. 
2736  *  \throw If the coordinates array is not set.
2737  *  \throw If the nodal connectivity of cells is not defined.
2738  *
2739  *  \if ENABLE_EXAMPLES
2740  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2741  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2742  *  \endif
2743  */
2744 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2745 {
2746   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2747   if(getMeshDimension()==-1)
2748     {
2749       elems->pushBackSilent(0);
2750       return elems.retn();
2751     }
2752   int dim=getSpaceDimension();
2753   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2754   const int* conn      = getNodalConnectivity()->getConstPointer();
2755   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2756   const double* coords = getCoords()->getConstPointer();
2757   int nbOfCells=getNumberOfCells();
2758   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2759     {
2760       for (int i=0; i<dim; i++)
2761         {
2762           elem_bb[i*2]=std::numeric_limits<double>::max();
2763           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2764         }
2765
2766       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2767         {
2768           int node= conn[inode];
2769           if(node>=0)//avoid polyhedron separator
2770             {
2771               for (int idim=0; idim<dim; idim++)
2772                 {
2773                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2774                     {
2775                       elem_bb[idim*2] = coords[node*dim+idim] ;
2776                     }
2777                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2778                     {
2779                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2780                     }
2781                 }
2782             }
2783         }
2784       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2785         elems->pushBackSilent(ielem);
2786     }
2787   return elems.retn();
2788 }
2789
2790 /*!
2791  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2792  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2793  * added in 'elems' parameter.
2794  */
2795 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2796 {
2797   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2798   if(getMeshDimension()==-1)
2799     {
2800       elems->pushBackSilent(0);
2801       return elems.retn();
2802     }
2803   int dim=getSpaceDimension();
2804   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2805   const int* conn      = getNodalConnectivity()->getConstPointer();
2806   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2807   const double* coords = getCoords()->getConstPointer();
2808   int nbOfCells=getNumberOfCells();
2809   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2810     {
2811       for (int i=0; i<dim; i++)
2812         {
2813           elem_bb[i*2]=std::numeric_limits<double>::max();
2814           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2815         }
2816
2817       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2818         {
2819           int node= conn[inode];
2820           if(node>=0)//avoid polyhedron separator
2821             {
2822               for (int idim=0; idim<dim; idim++)
2823                 {
2824                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2825                     {
2826                       elem_bb[idim*2] = coords[node*dim+idim] ;
2827                     }
2828                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2829                     {
2830                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2831                     }
2832                 }
2833             }
2834         }
2835       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2836         elems->pushBackSilent(ielem);
2837     }
2838   return elems.retn();
2839 }
2840
2841 /*!
2842  * Returns a type of a cell by its id.
2843  *  \param [in] cellId - the id of the cell of interest.
2844  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2845  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2846  */
2847 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2848 {
2849   const int *ptI=_nodal_connec_index->getConstPointer();
2850   const int *pt=_nodal_connec->getConstPointer();
2851   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2852     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2853   else
2854     {
2855       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2856       throw INTERP_KERNEL::Exception(oss.str().c_str());
2857     }
2858 }
2859
2860 /*!
2861  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2862  * This method does not throw exception if geometric type \a type is not in \a this.
2863  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2864  * The coordinates array is not considered here.
2865  *
2866  * \param [in] type the geometric type
2867  * \return cell ids in this having geometric type \a type.
2868  */
2869 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2870 {
2871
2872   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2873   ret->alloc(0,1);
2874   checkConnectivityFullyDefined();
2875   int nbCells=getNumberOfCells();
2876   int mdim=getMeshDimension();
2877   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2878   if(mdim!=(int)cm.getDimension())
2879     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2880   const int *ptI=_nodal_connec_index->getConstPointer();
2881   const int *pt=_nodal_connec->getConstPointer();
2882   for(int i=0;i<nbCells;i++)
2883     {
2884       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2885         ret->pushBackSilent(i);
2886     }
2887   return ret.retn();
2888 }
2889
2890 /*!
2891  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2892  */
2893 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2894 {
2895   const int *ptI=_nodal_connec_index->getConstPointer();
2896   const int *pt=_nodal_connec->getConstPointer();
2897   int nbOfCells=getNumberOfCells();
2898   int ret=0;
2899   for(int i=0;i<nbOfCells;i++)
2900     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2901       ret++;
2902   return ret;
2903 }
2904
2905 /*!
2906  * Returns the nodal connectivity of a given cell.
2907  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2908  * all returned node ids can be used in getCoordinatesOfNode().
2909  *  \param [in] cellId - an id of the cell of interest.
2910  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2911  *         cleared before the appending.
2912  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2913  */
2914 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2915 {
2916   const int *ptI=_nodal_connec_index->getConstPointer();
2917   const int *pt=_nodal_connec->getConstPointer();
2918   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2919     if(*w>=0)
2920       conn.push_back(*w);
2921 }
2922
2923 std::string MEDCouplingUMesh::simpleRepr() const
2924 {
2925   static const char msg0[]="No coordinates specified !";
2926   std::ostringstream ret;
2927   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2928   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2929   int tmpp1,tmpp2;
2930   double tt=getTime(tmpp1,tmpp2);
2931   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2932   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2933   if(_mesh_dim>=-1)
2934     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2935   else
2936     { ret << " Mesh dimension has not been set or is invalid !"; }
2937   if(_coords!=0)
2938     {
2939       const int spaceDim=getSpaceDimension();
2940       ret << spaceDim << "\nInfo attached on space dimension : ";
2941       for(int i=0;i<spaceDim;i++)
2942         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2943       ret << "\n";
2944     }
2945   else
2946     ret << msg0 << "\n";
2947   ret << "Number of nodes : ";
2948   if(_coords!=0)
2949     ret << getNumberOfNodes() << "\n";
2950   else
2951     ret << msg0 << "\n";
2952   ret << "Number of cells : ";
2953   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2954     ret << getNumberOfCells() << "\n";
2955   else
2956     ret << "No connectivity specified !" << "\n";
2957   ret << "Cell types present : ";
2958   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2959     {
2960       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2961       ret << cm.getRepr() << " ";
2962     }
2963   ret << "\n";
2964   return ret.str();
2965 }
2966
2967 std::string MEDCouplingUMesh::advancedRepr() const
2968 {
2969   std::ostringstream ret;
2970   ret << simpleRepr();
2971   ret << "\nCoordinates array : \n___________________\n\n";
2972   if(_coords)
2973     _coords->reprWithoutNameStream(ret);
2974   else
2975     ret << "No array set !\n";
2976   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2977   reprConnectivityOfThisLL(ret);
2978   return ret.str();
2979 }
2980
2981 /*!
2982  * This method returns a C++ code that is a dump of \a this.
2983  * This method will throw if this is not fully defined.
2984  */
2985 std::string MEDCouplingUMesh::cppRepr() const
2986 {
2987   static const char coordsName[]="coords";
2988   static const char connName[]="conn";
2989   static const char connIName[]="connI";
2990   checkFullyDefined();
2991   std::ostringstream ret; ret << "// coordinates" << std::endl;
2992   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2993   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2994   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2995   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2996   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2997   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2998   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2999   return ret.str();
3000 }
3001
3002 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
3003 {
3004   std::ostringstream ret;
3005   reprConnectivityOfThisLL(ret);
3006   return ret.str();
3007 }
3008
3009 /*!
3010  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
3011  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
3012  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
3013  * some algos).
3014  * 
3015  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
3016  * 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
3017  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
3018  */
3019 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
3020 {
3021   int mdim=getMeshDimension();
3022   if(mdim<0)
3023     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
3024   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
3025   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
3026   bool needToCpyCT=true;
3027   if(!_nodal_connec)
3028     {
3029       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
3030       needToCpyCT=false;
3031     }
3032   else
3033     {
3034       tmp1=_nodal_connec;
3035       tmp1->incrRef();
3036     }
3037   if(!_nodal_connec_index)
3038     {
3039       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
3040       needToCpyCT=false;
3041     }
3042   else
3043     {
3044       tmp2=_nodal_connec_index;
3045       tmp2->incrRef();
3046     }
3047   ret->setConnectivity(tmp1,tmp2,false);
3048   if(needToCpyCT)
3049     ret->_types=_types;
3050   if(!_coords)
3051     {
3052       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
3053       ret->setCoords(coords);
3054     }
3055   else
3056     ret->setCoords(_coords);
3057   return ret.retn();
3058 }
3059
3060 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
3061 {
3062   if(_nodal_connec!=0 && _nodal_connec_index!=0)
3063     {
3064       int nbOfCells=getNumberOfCells();
3065       const int *c=_nodal_connec->getConstPointer();
3066       const int *ci=_nodal_connec_index->getConstPointer();
3067       for(int i=0;i<nbOfCells;i++)
3068         {
3069           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
3070           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
3071           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
3072           stream << "\n";
3073         }
3074     }
3075   else
3076     stream << "Connectivity not defined !\n";
3077 }
3078
3079 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
3080 {
3081   const int *ptI=_nodal_connec_index->getConstPointer();
3082   const int *pt=_nodal_connec->getConstPointer();
3083   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
3084     return ptI[cellId+1]-ptI[cellId]-1;
3085   else
3086     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
3087 }
3088
3089 /*!
3090  * Returns types of cells of the specified part of \a this mesh.
3091  * This method avoids computing sub-mesh explicitely to get its types.
3092  *  \param [in] begin - an array of cell ids of interest.
3093  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3094  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
3095  *         describing the cell types. 
3096  *  \throw If the coordinates array is not set.
3097  *  \throw If the nodal connectivity of cells is not defined.
3098  *  \sa getAllGeoTypes()
3099  */
3100 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
3101 {
3102   checkFullyDefined();
3103   std::set<INTERP_KERNEL::NormalizedCellType> ret;
3104   const int *conn=_nodal_connec->getConstPointer();
3105   const int *connIndex=_nodal_connec_index->getConstPointer();
3106   for(const int *w=begin;w!=end;w++)
3107     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
3108   return ret;
3109 }
3110
3111 /*!
3112  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
3113  * a set of types of cells constituting \a this mesh. 
3114  * This method is for advanced users having prepared their connectivity before. For
3115  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
3116  *  \param [in] conn - the nodal connectivity array. 
3117  *  \param [in] connIndex - the nodal connectivity index array.
3118  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3119  *         mesh is updated.
3120  */
3121 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3122 {
3123   DataArrayInt::SetArrayIn(conn,_nodal_connec);
3124   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3125   if(isComputingTypes)
3126     computeTypes();
3127   declareAsNew();
3128 }
3129
3130 /*!
3131  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3132  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3133  */
3134 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3135     _nodal_connec(0),_nodal_connec_index(0),
3136     _types(other._types)
3137 {
3138   if(other._nodal_connec)
3139     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3140   if(other._nodal_connec_index)
3141     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3142 }
3143
3144 MEDCouplingUMesh::~MEDCouplingUMesh()
3145 {
3146   if(_nodal_connec)
3147     _nodal_connec->decrRef();
3148   if(_nodal_connec_index)
3149     _nodal_connec_index->decrRef();
3150 }
3151
3152 /*!
3153  * Recomputes a set of cell types of \a this mesh. For more info see
3154  * \ref MEDCouplingUMeshNodalConnectivity.
3155  */
3156 void MEDCouplingUMesh::computeTypes()
3157 {
3158   ComputeAllTypesInternal(_types,_nodal_connec,_nodal_connec_index);
3159 }
3160
3161 /*!
3162  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3163  */
3164 void MEDCouplingUMesh::checkFullyDefined() const
3165 {
3166   if(!_nodal_connec_index || !_nodal_connec || !_coords)
3167     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3168 }
3169
3170 /*!
3171  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3172  */
3173 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3174 {
3175   if(!_nodal_connec_index || !_nodal_connec)
3176     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3177 }
3178
3179 /*!
3180  * Returns a number of cells constituting \a this mesh. 
3181  *  \return int - the number of cells in \a this mesh.
3182  *  \throw If the nodal connectivity of cells is not defined.
3183  */
3184 int MEDCouplingUMesh::getNumberOfCells() const
3185
3186   if(_nodal_connec_index)
3187     return _nodal_connec_index->getNumberOfTuples()-1;
3188   else
3189     if(_mesh_dim==-1)
3190       return 1;
3191     else
3192       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3193 }
3194
3195 /*!
3196  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3197  * mesh. For more info see \ref MEDCouplingMeshesPage.
3198  *  \return int - the dimension of \a this mesh.
3199  *  \throw If the mesh dimension is not defined using setMeshDimension().
3200  */
3201 int MEDCouplingUMesh::getMeshDimension() const
3202 {
3203   if(_mesh_dim<-1)
3204     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3205   return _mesh_dim;
3206 }
3207
3208 /*!
3209  * Returns a length of the nodal connectivity array.
3210  * This method is for test reason. Normally the integer returned is not useable by
3211  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
3212  *  \return int - the length of the nodal connectivity array.
3213  */
3214 int MEDCouplingUMesh::getMeshLength() const
3215 {
3216   return _nodal_connec->getNbOfElems();
3217 }
3218
3219 /*!
3220  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3221  */
3222 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3223 {
3224   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3225   tinyInfo.push_back(getMeshDimension());
3226   tinyInfo.push_back(getNumberOfCells());
3227   if(_nodal_connec)
3228     tinyInfo.push_back(getMeshLength());
3229   else
3230     tinyInfo.push_back(-1);
3231 }
3232
3233 /*!
3234  * First step of unserialization process.
3235  */
3236 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3237 {
3238   return tinyInfo[6]<=0;
3239 }
3240
3241 /*!
3242  * Second step of serialization process.
3243  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3244  */
3245 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3246 {
3247   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3248   if(tinyInfo[5]!=-1)
3249     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3250 }
3251
3252 /*!
3253  * Third and final step of serialization process.
3254  */
3255 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3256 {
3257   MEDCouplingPointSet::serialize(a1,a2);
3258   if(getMeshDimension()>-1)
3259     {
3260       a1=DataArrayInt::New();
3261       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3262       int *ptA1=a1->getPointer();
3263       const int *conn=getNodalConnectivity()->getConstPointer();
3264       const int *index=getNodalConnectivityIndex()->getConstPointer();
3265       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3266       std::copy(conn,conn+getMeshLength(),ptA1);
3267     }
3268   else
3269     a1=0;
3270 }
3271
3272 /*!
3273  * Second and final unserialization process.
3274  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3275  */
3276 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3277 {
3278   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3279   setMeshDimension(tinyInfo[5]);
3280   if(tinyInfo[7]!=-1)
3281     {
3282       // Connectivity
3283       const int *recvBuffer=a1->getConstPointer();
3284       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3285       myConnecIndex->alloc(tinyInfo[6]+1,1);
3286       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3287       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3288       myConnec->alloc(tinyInfo[7],1);
3289       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3290       setConnectivity(myConnec, myConnecIndex);
3291     }
3292 }
3293
3294 /*!
3295  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3296  * CellIds are given using range specified by a start an end and step.
3297  */
3298 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3299 {
3300   checkFullyDefined();
3301   int ncell=getNumberOfCells();
3302   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3303   ret->_mesh_dim=_mesh_dim;
3304   ret->setCoords(_coords);
3305   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3306   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3307   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3308   int work=start;
3309   const int *conn=_nodal_connec->getConstPointer();
3310   const int *connIndex=_nodal_connec_index->getConstPointer();
3311   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3312     {
3313       if(work>=0 && work<ncell)
3314         {
3315           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3316         }
3317       else
3318         {
3319           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3320           throw INTERP_KERNEL::Exception(oss.str().c_str());
3321         }
3322     }
3323   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3324   int *newConnPtr=newConn->getPointer();
3325   std::set<INTERP_KERNEL::NormalizedCellType> types;
3326   work=start;
3327   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3328     {
3329       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3330       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3331     }
3332   ret->setConnectivity(newConn,newConnI,false);
3333   ret->_types=types;
3334   ret->copyTinyInfoFrom(this);
3335   return ret.retn();
3336 }
3337
3338 /*!
3339  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3340  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3341  * The return newly allocated mesh will share the same coordinates as \a this.
3342  */
3343 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3344 {
3345   checkConnectivityFullyDefined();
3346   int ncell=getNumberOfCells();
3347   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3348   ret->_mesh_dim=_mesh_dim;
3349   ret->setCoords(_coords);
3350   std::size_t nbOfElemsRet=std::distance(begin,end);
3351   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3352   connIndexRet[0]=0;
3353   const int *conn=_nodal_connec->getConstPointer();
3354   const int *connIndex=_nodal_connec_index->getConstPointer();
3355   int newNbring=0;
3356   for(const int *work=begin;work!=end;work++,newNbring++)
3357     {
3358       if(*work>=0 && *work<ncell)
3359         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3360       else
3361         {
3362           free(connIndexRet);
3363           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3364           throw INTERP_KERNEL::Exception(oss.str().c_str());
3365         }
3366     }
3367   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3368   int *connRetWork=connRet;
3369   std::set<INTERP_KERNEL::NormalizedCellType> types;
3370   for(const int *work=begin;work!=end;work++)
3371     {
3372       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3373       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3374     }
3375   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3376   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3377   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3378   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3379   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3380   ret->_types=types;
3381   ret->copyTinyInfoFrom(this);
3382   return ret.retn();
3383 }
3384
3385 /*!
3386  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3387  * mesh.<br>
3388  * For 1D cells, the returned field contains lengths.<br>
3389  * For 2D cells, the returned field contains areas.<br>
3390  * For 3D cells, the returned field contains volumes.
3391  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3392  *         orientation, i.e. the volume is always positive.
3393  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3394  *         and one time . The caller is to delete this field using decrRef() as it is no
3395  *         more needed.
3396  */
3397 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3398 {
3399   std::string name="MeasureOfMesh_";
3400   name+=getName();
3401   int nbelem=getNumberOfCells();
3402   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3403   field->setName(name);
3404   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3405   array->alloc(nbelem,1);
3406   double *area_vol=array->getPointer();
3407   field->setArray(array) ; array=0;
3408   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3409   field->synchronizeTimeWithMesh();
3410   if(getMeshDimension()!=-1)
3411     {
3412       int ipt;
3413       INTERP_KERNEL::NormalizedCellType type;
3414       int dim_space=getSpaceDimension();
3415       const double *coords=getCoords()->getConstPointer();
3416       const int *connec=getNodalConnectivity()->getConstPointer();
3417       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3418       for(int iel=0;iel<nbelem;iel++)
3419         {
3420           ipt=connec_index[iel];
3421           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3422           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);
3423         }
3424       if(isAbs)
3425         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3426     }
3427   else
3428     {
3429       area_vol[0]=std::numeric_limits<double>::max();
3430     }
3431   return field.retn();
3432 }
3433
3434 /*!
3435  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3436  * mesh.<br>
3437  * For 1D cells, the returned array contains lengths.<br>
3438  * For 2D cells, the returned array contains areas.<br>
3439  * For 3D cells, the returned array contains volumes.
3440  * This method avoids building explicitly a part of \a this mesh to perform the work.
3441  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3442  *         orientation, i.e. the volume is always positive.
3443  *  \param [in] begin - an array of cell ids of interest.
3444  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3445  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3446  *          delete this array using decrRef() as it is no more needed.
3447  * 
3448  *  \if ENABLE_EXAMPLES
3449  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3450  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3451  *  \endif
3452  *  \sa getMeasureField()
3453  */
3454 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3455 {
3456   std::string name="PartMeasureOfMesh_";
3457   name+=getName();
3458   int nbelem=(int)std::distance(begin,end);
3459   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3460   array->setName(name);
3461   array->alloc(nbelem,1);
3462   double *area_vol=array->getPointer();
3463   if(getMeshDimension()!=-1)
3464     {
3465       int ipt;
3466       INTERP_KERNEL::NormalizedCellType type;
3467       int dim_space=getSpaceDimension();
3468       const double *coords=getCoords()->getConstPointer();
3469       const int *connec=getNodalConnectivity()->getConstPointer();
3470       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3471       for(const int *iel=begin;iel!=end;iel++)
3472         {
3473           ipt=connec_index[*iel];
3474           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3475           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3476         }
3477       if(isAbs)
3478         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3479     }
3480   else
3481     {
3482       area_vol[0]=std::numeric_limits<double>::max();
3483     }
3484   return array.retn();
3485 }
3486
3487 /*!
3488  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3489  * \a this one. The returned field contains the dual cell volume for each corresponding
3490  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3491  *  the dual mesh in P1 sens of \a this.<br>
3492  * For 1D cells, the returned field contains lengths.<br>
3493  * For 2D cells, the returned field contains areas.<br>
3494  * For 3D cells, the returned field contains volumes.
3495  * This method is useful to check "P1*" conservative interpolators.
3496  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3497  *         orientation, i.e. the volume is always positive.
3498  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3499  *          nodes and one time. The caller is to delete this array using decrRef() as
3500  *          it is no more needed.
3501  */
3502 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3503 {
3504   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3505   std::string name="MeasureOnNodeOfMesh_";
3506   name+=getName();
3507   int nbNodes=getNumberOfNodes();
3508   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3509   double cst=1./((double)getMeshDimension()+1.);
3510   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3511   array->alloc(nbNodes,1);
3512   double *valsToFill=array->getPointer();
3513   std::fill(valsToFill,valsToFill+nbNodes,0.);
3514   const double *values=tmp->getArray()->getConstPointer();
3515   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3516   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3517   getReverseNodalConnectivity(da,daInd);
3518   const int *daPtr=da->getConstPointer();
3519   const int *daIPtr=daInd->getConstPointer();
3520   for(int i=0;i<nbNodes;i++)
3521     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3522       valsToFill[i]+=cst*values[*cell];
3523   ret->setMesh(this);
3524   ret->setArray(array);
3525   return ret.retn();
3526 }
3527
3528 /*!
3529  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3530  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3531  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3532  * and are normalized.
3533  * <br> \a this can be either 
3534  * - a  2D mesh in 2D or 3D space or 
3535  * - an 1D mesh in 2D space.
3536  * 
3537  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3538  *          cells and one time. The caller is to delete this field using decrRef() as
3539  *          it is no more needed.
3540  *  \throw If the nodal connectivity of cells is not defined.
3541  *  \throw If the coordinates array is not set.
3542  *  \throw If the mesh dimension is not set.
3543  *  \throw If the mesh and space dimension is not as specified above.
3544  */
3545 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3546 {
3547   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3548     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3549   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3550   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3551   int nbOfCells=getNumberOfCells();
3552   int nbComp=getMeshDimension()+1;
3553   array->alloc(nbOfCells,nbComp);
3554   double *vals=array->getPointer();
3555   const int *connI=_nodal_connec_index->getConstPointer();
3556   const int *conn=_nodal_connec->getConstPointer();
3557   const double *coords=_coords->getConstPointer();
3558   if(getMeshDimension()==2)
3559     {
3560       if(getSpaceDimension()==3)
3561         {
3562           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3563           const double *locPtr=loc->getConstPointer();
3564           for(int i=0;i<nbOfCells;i++,vals+=3)
3565             {
3566               int offset=connI[i];
3567               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3568               double n=INTERP_KERNEL::norm<3>(vals);
3569               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3570             }
3571         }
3572       else
3573         {
3574           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3575           const double *isAbsPtr=isAbs->getArray()->begin();
3576           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3577             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3578         }
3579     }
3580   else//meshdimension==1
3581     {
3582       double tmp[2];
3583       for(int i=0;i<nbOfCells;i++)
3584         {
3585           int offset=connI[i];
3586           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3587           double n=INTERP_KERNEL::norm<2>(tmp);
3588           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3589           *vals++=-tmp[1];
3590           *vals++=tmp[0];
3591         }
3592     }
3593   ret->setArray(array);
3594   ret->setMesh(this);
3595   ret->synchronizeTimeWithSupport();
3596   return ret.retn();
3597 }
3598
3599 /*!
3600  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3601  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3602  * and are normalized.
3603  * <br> \a this can be either 
3604  * - a  2D mesh in 2D or 3D space or 
3605  * - an 1D mesh in 2D space.
3606  * 
3607  * This method avoids building explicitly a part of \a this mesh to perform the work.
3608  *  \param [in] begin - an array of cell ids of interest.
3609  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3610  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3611  *          cells and one time. The caller is to delete this field using decrRef() as
3612  *          it is no more needed.
3613  *  \throw If the nodal connectivity of cells is not defined.
3614  *  \throw If the coordinates array is not set.
3615  *  \throw If the mesh dimension is not set.
3616  *  \throw If the mesh and space dimension is not as specified above.
3617  *  \sa buildOrthogonalField()
3618  *
3619  *  \if ENABLE_EXAMPLES
3620  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3621  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3622  *  \endif
3623  */
3624 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3625 {
3626   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3627     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3628   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3629   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3630   std::size_t nbelems=std::distance(begin,end);
3631   int nbComp=getMeshDimension()+1;
3632   array->alloc((int)nbelems,nbComp);
3633   double *vals=array->getPointer();
3634   const int *connI=_nodal_connec_index->getConstPointer();
3635   const int *conn=_nodal_connec->getConstPointer();
3636   const double *coords=_coords->getConstPointer();
3637   if(getMeshDimension()==2)
3638     {
3639       if(getSpaceDimension()==3)
3640         {
3641           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3642           const double *locPtr=loc->getConstPointer();
3643           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3644             {
3645               int offset=connI[*i];
3646               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3647               double n=INTERP_KERNEL::norm<3>(vals);
3648               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3649             }
3650         }
3651       else
3652         {
3653           for(std::size_t i=0;i<nbelems;i++)
3654             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3655         }
3656     }
3657   else//meshdimension==1
3658     {
3659       double tmp[2];
3660       for(const int *i=begin;i!=end;i++)
3661         {
3662           int offset=connI[*i];
3663           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3664           double n=INTERP_KERNEL::norm<2>(tmp);
3665           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3666           *vals++=-tmp[1];
3667           *vals++=tmp[0];
3668         }
3669     }
3670   ret->setArray(array);
3671   ret->setMesh(this);
3672   ret->synchronizeTimeWithSupport();
3673   return ret.retn();
3674 }
3675
3676 /*!
3677  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3678  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3679  * and are \b not normalized.
3680  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3681  *          cells and one time. The caller is to delete this field using decrRef() as
3682  *          it is no more needed.
3683  *  \throw If the nodal connectivity of cells is not defined.
3684  *  \throw If the coordinates array is not set.
3685  *  \throw If \a this->getMeshDimension() != 1.
3686  *  \throw If \a this mesh includes cells of type other than SEG2.
3687  */
3688 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3689 {
3690   if(getMeshDimension()!=1)
3691     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3692   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3693     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3694   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3695   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3696   int nbOfCells=getNumberOfCells();
3697   int spaceDim=getSpaceDimension();
3698   array->alloc(nbOfCells,spaceDim);
3699   double *pt=array->getPointer();
3700   const double *coo=getCoords()->getConstPointer();
3701   std::vector<int> conn;
3702   conn.reserve(2);
3703   for(int i=0;i<nbOfCells;i++)
3704     {
3705       conn.resize(0);
3706       getNodeIdsOfCell(i,conn);
3707       pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3708     }
3709   ret->setArray(array);
3710   ret->setMesh(this);
3711   ret->synchronizeTimeWithSupport();
3712   return ret.retn();
3713 }
3714
3715 /*!
3716  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3717  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3718  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3719  * from. If a result face is shared by two 3D cells, then the face in included twice in
3720  * the result mesh.
3721  *  \param [in] origin - 3 components of a point defining location of the plane.
3722  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3723  *         must be greater than 1e-6.
3724  *  \param [in] eps - half-thickness of the plane.
3725  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3726  *         producing correspondent 2D cells. The caller is to delete this array
3727  *         using decrRef() as it is no more needed.
3728  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3729  *         not share the node coordinates array with \a this mesh. The caller is to
3730  *         delete this mesh using decrRef() as it is no more needed.  
3731  *  \throw If the coordinates array is not set.
3732  *  \throw If the nodal connectivity of cells is not defined.
3733  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3734  *  \throw If magnitude of \a vec is less than 1e-6.
3735  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3736  *  \throw If \a this includes quadratic cells.
3737  */
3738 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3739 {
3740   checkFullyDefined();
3741   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3742     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3743   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3744   if(candidates->empty())
3745     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3746   std::vector<int> nodes;
3747   DataArrayInt *cellIds1D=0;
3748   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3749   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3750   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3751   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3752   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3753   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3754   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3755   revDesc2=0; revDescIndx2=0;
3756   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3757   revDesc1=0; revDescIndx1=0;
3758   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3759   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3760   //
3761   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3762   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3763     cut3DCurve[*it]=-1;
3764   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3765   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3766   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3767                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3768                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3769   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3770   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3771   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3772   if(cellIds2->empty())
3773     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3774   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3775   ret->setCoords(mDesc1->getCoords());
3776   ret->setConnectivity(conn,connI,true);
3777   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3778   return ret.retn();
3779 }
3780
3781 /*!
3782  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3783 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
3784 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3785 the result mesh.
3786  *  \param [in] origin - 3 components of a point defining location of the plane.
3787  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3788  *         must be greater than 1e-6.
3789  *  \param [in] eps - half-thickness of the plane.
3790  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3791  *         producing correspondent segments. The caller is to delete this array
3792  *         using decrRef() as it is no more needed.
3793  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3794  *         mesh in 3D space. This mesh does not share the node coordinates array with
3795  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3796  *         no more needed. 
3797  *  \throw If the coordinates array is not set.
3798  *  \throw If the nodal connectivity of cells is not defined.
3799  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3800  *  \throw If magnitude of \a vec is less than 1e-6.
3801  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3802  *  \throw If \a this includes quadratic cells.
3803  */
3804 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3805 {
3806   checkFullyDefined();
3807   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3808     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3809   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3810   if(candidates->empty())
3811     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3812   std::vector<int> nodes;
3813   DataArrayInt *cellIds1D=0;
3814   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3815   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3816   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3817   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3818   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3819   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3820   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3821   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3822   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3823   //
3824   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3825   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3826     cut3DCurve[*it]=-1;
3827   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3828   int ncellsSub=subMesh->getNumberOfCells();
3829   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3830   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3831                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3832                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3833   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3834   conn->alloc(0,1);
3835   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3836   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3837   for(int i=0;i<ncellsSub;i++)
3838     {
3839       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3840         {
3841           if(cut3DSurf[i].first!=-2)
3842             {
3843               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3844               connI->pushBackSilent(conn->getNumberOfTuples());
3845               cellIds2->pushBackSilent(i);
3846             }
3847           else
3848             {
3849               int cellId3DSurf=cut3DSurf[i].second;
3850               int offset=nodalI[cellId3DSurf]+1;
3851               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3852               for(int j=0;j<nbOfEdges;j++)
3853                 {
3854                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3855                   connI->pushBackSilent(conn->getNumberOfTuples());
3856                   cellIds2->pushBackSilent(cellId3DSurf);
3857                 }
3858             }
3859         }
3860     }
3861   if(cellIds2->empty())
3862     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3863   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3864   ret->setCoords(mDesc1->getCoords());
3865   ret->setConnectivity(conn,connI,true);
3866   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3867   return ret.retn();
3868 }
3869
3870 /*!
3871  * Finds cells whose bounding boxes intersect a given plane.
3872  *  \param [in] origin - 3 components of a point defining location of the plane.
3873  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3874  *         must be greater than 1e-6.
3875  *  \param [in] eps - half-thickness of the plane.
3876  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3877  *         cells. The caller is to delete this array using decrRef() as it is no more
3878  *         needed.
3879  *  \throw If the coordinates array is not set.
3880  *  \throw If the nodal connectivity of cells is not defined.
3881  *  \throw If \a this->getSpaceDimension() != 3.
3882  *  \throw If magnitude of \a vec is less than 1e-6.
3883  *  \sa buildSlice3D()
3884  */
3885 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3886 {
3887   checkFullyDefined();
3888   if(getSpaceDimension()!=3)
3889     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3890   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3891   if(normm<1e-6)
3892     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3893   double vec2[3];
3894   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3895   double angle=acos(vec[2]/normm);
3896   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3897   double bbox[6];
3898   if(angle>eps)
3899     {
3900       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3901       double normm2(sqrt(vec2[0]*vec2[0]+vec2[1]*vec2[1]+vec2[2]*vec2[2]));
3902       if(normm2/normm>1e-6)
3903         MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3904       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3905       mw->setCoords(coo);
3906       mw->getBoundingBox(bbox);
3907       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3908       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3909     }
3910   else
3911     {
3912       getBoundingBox(bbox);
3913       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3914       cellIds=getCellsInBoundingBox(bbox,eps);
3915     }
3916   return cellIds.retn();
3917 }
3918
3919 /*!
3920  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3921  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3922  * No consideration of coordinate is done by this method.
3923  * 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)
3924  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3925  */
3926 bool MEDCouplingUMesh::isContiguous1D() const
3927 {
3928   if(getMeshDimension()!=1)
3929     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3930   int nbCells=getNumberOfCells();
3931   if(nbCells<1)
3932     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3933   const int *connI=_nodal_connec_index->getConstPointer();
3934   const int *conn=_nodal_connec->getConstPointer();
3935   int ref=conn[connI[0]+2];
3936   for(int i=1;i<nbCells;i++)
3937     {
3938       if(conn[connI[i]+1]!=ref)
3939         return false;
3940       ref=conn[connI[i]+2];
3941     }
3942   return true;
3943 }
3944
3945 /*!
3946  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3947  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3948  * \param pt reference point of the line
3949  * \param v normalized director vector of the line
3950  * \param eps max precision before throwing an exception
3951  * \param res output of size this->getNumberOfCells
3952  */
3953 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3954 {
3955   if(getMeshDimension()!=1)
3956     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3957   if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3958     throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3959   if(getSpaceDimension()!=3)
3960     throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3961   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3962   const double *fPtr=f->getArray()->getConstPointer();
3963   double tmp[3];
3964   for(int i=0;i<getNumberOfCells();i++)
3965     {
3966       const double *tmp1=fPtr+3*i;
3967       tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3968       tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3969       tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3970       double n1=INTERP_KERNEL::norm<3>(tmp);
3971       n1/=INTERP_KERNEL::norm<3>(tmp1);
3972       if(n1>eps)
3973         throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3974     }
3975   const double *coo=getCoords()->getConstPointer();
3976   for(int i=0;i<getNumberOfNodes();i++)
3977     {
3978       std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3979       std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3980       res[i]=std::accumulate(tmp,tmp+3,0.);
3981     }
3982 }
3983
3984 /*!
3985  * 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. 
3986  * \a this is expected to be a mesh so that its space dimension is equal to its
3987  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3988  * 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).
3989  *
3990  * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3991  * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3992  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3993  *
3994  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3995  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3996  *
3997  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3998  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3999  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4000  * \return the positive value of the distance.
4001  * \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
4002  * dimension - 1.
4003  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
4004  */
4005 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
4006 {
4007   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4008   if(meshDim!=spaceDim-1)
4009     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
4010   if(meshDim!=2 && meshDim!=1)
4011     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
4012   checkFullyDefined();
4013   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
4014     { 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()); }
4015   DataArrayInt *ret1=0;
4016   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
4017   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
4018   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
4019   cellId=*ret1Safe->begin();
4020   return *ret0->begin();
4021 }
4022
4023 /*!
4024  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
4025  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
4026  * 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
4027  * 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).
4028  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
4029  * 
4030  * \a this is expected to be a mesh so that its space dimension is equal to its
4031  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
4032  * 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).
4033  *
4034  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
4035  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
4036  *
4037  * \param [in] pts the list of points in which each tuple represents a point
4038  * \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.
4039  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
4040  * \throw if number of components of \a pts is not equal to the space dimension.
4041  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
4042  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
4043  */
4044 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
4045 {
4046   if(!pts)
4047     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
4048   pts->checkAllocated();
4049   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
4050   if(meshDim!=spaceDim-1)
4051     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
4052   if(meshDim!=2 && meshDim!=1)
4053     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
4054   if(pts->getNumberOfComponents()!=spaceDim)
4055     {
4056       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
4057       throw INTERP_KERNEL::Exception(oss.str().c_str());
4058     }
4059   checkFullyDefined();
4060   int nbCells=getNumberOfCells();
4061   if(nbCells==0)
4062     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
4063   int nbOfPts=pts->getNumberOfTuples();
4064   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
4065   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
4066   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
4067   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
4068   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4069   const double *bbox(bboxArr->begin());
4070   switch(spaceDim)
4071   {
4072     case 3:
4073       {
4074         BBTreeDst<3> myTree(bbox,0,0,nbCells);
4075         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
4076           {
4077             double x=std::numeric_limits<double>::max();
4078             std::vector<int> elems;
4079             myTree.getMinDistanceOfMax(ptsPtr,x);
4080             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4081             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4082           }
4083         break;
4084       }
4085     case 2:
4086       {
4087         BBTreeDst<2> myTree(bbox,0,0,nbCells);
4088         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
4089           {
4090             double x=std::numeric_limits<double>::max();
4091             std::vector<int> elems;
4092             myTree.getMinDistanceOfMax(ptsPtr,x);
4093             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
4094             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
4095           }
4096         break;
4097       }
4098     default:
4099       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
4100   }
4101   cellIds=ret1.retn();
4102   return ret0.retn();
4103 }
4104
4105 /*!
4106  * \param [in] pt the start pointer (included) of the coordinates of the point
4107  * \param [in] cellIdsBg the start pointer (included) of cellIds
4108  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4109  * \param [in] nc nodal connectivity
4110  * \param [in] ncI nodal connectivity index
4111  * \param [in,out] ret0 the min distance between \a this and the external input point
4112  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4113  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4114  */
4115 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)
4116 {
4117   cellId=-1;
4118   ret0=std::numeric_limits<double>::max();
4119   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4120     {
4121       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4122       {
4123         case INTERP_KERNEL::NORM_TRI3:
4124           {
4125             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4126             if(tmp<ret0)
4127               { ret0=tmp; cellId=*zeCell; }
4128             break;
4129           }
4130         case INTERP_KERNEL::NORM_QUAD4:
4131         case INTERP_KERNEL::NORM_POLYGON:
4132           {
4133             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4134             if(tmp<ret0)
4135               { ret0=tmp; cellId=*zeCell; }
4136             break;
4137           }
4138         default:
4139           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4140       }
4141     }
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::DistanceToPoint2DCurveAlg(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_SEG2:
4163           {
4164             std::size_t uselessEntry=0;
4165             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4166             tmp=sqrt(tmp);
4167             if(tmp<ret0)
4168               { ret0=tmp; cellId=*zeCell; }
4169             break;
4170           }
4171         default:
4172           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4173       }
4174     }
4175 }
4176
4177 /*!
4178  * Finds cells in contact with a ball (i.e. a point with precision). 
4179  * 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.
4180  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4181  *
4182  * \warning This method is suitable if the caller intends to evaluate only one
4183  *          point, for more points getCellsContainingPoints() is recommended as it is
4184  *          faster. 
4185  *  \param [in] pos - array of coordinates of the ball central point.
4186  *  \param [in] eps - ball radius.
4187  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
4188  *         if there are no such cells.
4189  *  \throw If the coordinates array is not set.
4190  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4191  */
4192 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4193 {
4194   std::vector<int> elts;
4195   getCellsContainingPoint(pos,eps,elts);
4196   if(elts.empty())
4197     return -1;
4198   return elts.front();
4199 }
4200
4201 /*!
4202  * Finds cells in contact with a ball (i.e. a point with precision).
4203  * 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.
4204  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4205  * \warning This method is suitable if the caller intends to evaluate only one
4206  *          point, for more points getCellsContainingPoints() is recommended as it is
4207  *          faster. 
4208  *  \param [in] pos - array of coordinates of the ball central point.
4209  *  \param [in] eps - ball radius.
4210  *  \param [out] elts - vector returning ids of the found cells. It is cleared
4211  *         before inserting ids.
4212  *  \throw If the coordinates array is not set.
4213  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4214  *
4215  *  \if ENABLE_EXAMPLES
4216  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4217  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
4218  *  \endif
4219  */
4220 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4221 {
4222   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4223   getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4224   elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4225 }
4226
4227 /// @cond INTERNAL
4228
4229 namespace ParaMEDMEM
4230 {
4231   template<const int SPACEDIMM>
4232   class DummyClsMCUG
4233   {
4234   public:
4235     static const int MY_SPACEDIM=SPACEDIMM;
4236     static const int MY_MESHDIM=8;
4237     typedef int MyConnType;
4238     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4239     // begin
4240     // useless, but for windows compilation ...
4241     const double* getCoordinatesPtr() const { return 0; }
4242     const int* getConnectivityPtr() const { return 0; }
4243     const int* getConnectivityIndexPtr() const { return 0; }
4244     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4245     // end
4246   };
4247
4248   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m)
4249   {
4250     INTERP_KERNEL::Edge *ret(0);
4251     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]));
4252     m[n0]=bg[0]; m[n1]=bg[1];
4253     switch(typ)
4254     {
4255       case INTERP_KERNEL::NORM_SEG2:
4256         {
4257           ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4258           break;
4259         }
4260       case INTERP_KERNEL::NORM_SEG3:
4261         {
4262           INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4263           INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4264           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4265           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4266           bool colinearity(inters.areColinears());
4267           delete e1; delete e2;
4268           if(colinearity)
4269             { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4270           else
4271             { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4272           break;
4273         }
4274       default:
4275         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4276     }
4277     return ret;
4278   }
4279
4280   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4281   {
4282     INTERP_KERNEL::Edge *ret=0;
4283     switch(typ)
4284     {
4285       case INTERP_KERNEL::NORM_SEG2:
4286         {
4287           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4288           break;
4289         }
4290       case INTERP_KERNEL::NORM_SEG3:
4291         {
4292           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4293           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4294           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4295           // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4296           bool colinearity=inters.areColinears();
4297           delete e1; delete e2;
4298           if(colinearity)
4299             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4300           else
4301             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4302           mapp2[bg[2]].second=false;
4303           break;
4304         }
4305       default:
4306         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4307     }
4308     return ret;
4309   }
4310
4311   /*!
4312    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4313    * the global mesh 'mDesc'.
4314    * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4315    * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4316    */
4317   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4318                                                                    std::map<INTERP_KERNEL::Node *,int>& mapp)
4319   {
4320     mapp.clear();
4321     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.
4322     const double *coo=mDesc->getCoords()->getConstPointer();
4323     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4324     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4325     std::set<int> s;
4326     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4327       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4328     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4329       {
4330         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4331         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4332       }
4333     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4334     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4335       {
4336         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4337         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4338       }
4339     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4340       {
4341         if((*it2).second.second)
4342           mapp[(*it2).second.first]=(*it2).first;
4343         ((*it2).second.first)->decrRef();
4344       }
4345     return ret;
4346   }
4347
4348   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4349   {
4350     if(nodeId>=offset2)
4351       {
4352         int locId=nodeId-offset2;
4353         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4354       }
4355     if(nodeId>=offset1)
4356       {
4357         int locId=nodeId-offset1;
4358         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4359       }
4360     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4361   }
4362
4363   /**
4364    * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4365    */
4366   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4367                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4368                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4369   {
4370     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4371       {
4372         int eltId1=abs(*desc1)-1;
4373         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4374           {
4375             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4376             if(it==mappRev.end())
4377               {
4378                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4379                 mapp[node]=*it1;
4380                 mappRev[*it1]=node;
4381               }
4382           }
4383       }
4384   }
4385 }
4386
4387 /// @endcond
4388
4389 template<int SPACEDIM>
4390 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4391                                                    double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4392 {
4393   elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4394   int *eltsIndexPtr(eltsIndex->getPointer());
4395   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4396   const double *bbox(bboxArr->begin());
4397   int nbOfCells=getNumberOfCells();
4398   const int *conn=_nodal_connec->getConstPointer();
4399   const int *connI=_nodal_connec_index->getConstPointer();
4400   double bb[2*SPACEDIM];
4401   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4402   for(int i=0;i<nbOfPoints;i++)
4403     {
4404       eltsIndexPtr[i+1]=eltsIndexPtr[i];
4405       for(int j=0;j<SPACEDIM;j++)
4406         {
4407           bb[2*j]=pos[SPACEDIM*i+j];
4408           bb[2*j+1]=pos[SPACEDIM*i+j];
4409         }
4410       std::vector<int> candidates;
4411       myTree.getIntersectingElems(bb,candidates);
4412       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4413         {
4414           int sz(connI[(*iter)+1]-connI[*iter]-1);
4415           INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4416           bool status(false);
4417           if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4418             status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4419           else
4420             {
4421               if(SPACEDIM!=2)
4422                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4423               INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4424               INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4425               std::vector<INTERP_KERNEL::Node *> nodes(sz);
4426               INTERP_KERNEL::QuadraticPolygon *pol(0);
4427               for(int j=0;j<sz;j++)
4428                 {
4429                   int nodeId(conn[connI[*iter]+1+j]);
4430                   nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4431                 }
4432               if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4433                 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4434               else
4435                 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4436               INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4437               double a(0.),b(0.),c(0.);
4438               a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4439               status=pol->isInOrOut2(n);
4440               delete pol; n->decrRef();
4441             }
4442           if(status)
4443             {
4444               eltsIndexPtr[i+1]++;
4445               elts->pushBackSilent(*iter);
4446             }
4447         }
4448     }
4449 }
4450 /*!
4451  * Finds cells in contact with several balls (i.e. points with precision).
4452  * This method is an extension of getCellContainingPoint() and
4453  * getCellsContainingPoint() for the case of multiple points.
4454  * 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.
4455  * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4456  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4457  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4458  *         this->getSpaceDimension() * \a nbOfPoints 
4459  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4460  *  \param [in] eps - radius of balls (i.e. the precision).
4461  *  \param [out] elts - vector returning ids of found cells.
4462  *  \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4463  *         dividing cell ids in \a elts into groups each referring to one
4464  *         point. Its every element (except the last one) is an index pointing to the
4465  *         first id of a group of cells. For example cells in contact with the *i*-th
4466  *         point are described by following range of indices:
4467  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4468  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4469  *         Number of cells in contact with the *i*-th point is
4470  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4471  *  \throw If the coordinates array is not set.
4472  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4473  *
4474  *  \if ENABLE_EXAMPLES
4475  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4476  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4477  *  \endif
4478  */
4479 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4480                                                 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4481 {
4482   int spaceDim=getSpaceDimension();
4483   int mDim=getMeshDimension();
4484   if(spaceDim==3)
4485     {
4486       if(mDim==3)
4487         {
4488           const double *coords=_coords->getConstPointer();
4489           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4490         }
4491       /*else if(mDim==2)
4492         {
4493
4494         }*/
4495       else
4496         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4497     }
4498   else if(spaceDim==2)
4499     {
4500       if(mDim==2)
4501         {
4502           const double *coords=_coords->getConstPointer();
4503           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4504         }
4505       else
4506         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4507     }
4508   else if(spaceDim==1)
4509     {
4510       if(mDim==1)
4511         {
4512           const double *coords=_coords->getConstPointer();
4513           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4514         }
4515       else
4516         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4517     }
4518   else
4519     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4520 }
4521
4522 /*!
4523  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4524  * least two its edges intersect each other anywhere except their extremities. An
4525  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4526  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4527  *         cleared before filling in.
4528  *  \param [in] eps - precision.
4529  *  \throw If \a this->getMeshDimension() != 2.
4530  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4531  */
4532 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4533 {
4534   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4535   if(getMeshDimension()!=2)
4536     throw INTERP_KERNEL::Exception(msg);
4537   int spaceDim=getSpaceDimension();
4538   if(spaceDim!=2 && spaceDim!=3)
4539     throw INTERP_KERNEL::Exception(msg);
4540   const int *conn=_nodal_connec->getConstPointer();
4541   const int *connI=_nodal_connec_index->getConstPointer();
4542   int nbOfCells=getNumberOfCells();
4543   std::vector<double> cell2DinS2;
4544   for(int i=0;i<nbOfCells;i++)
4545     {
4546       int offset=connI[i];
4547       int nbOfNodesForCell=connI[i+1]-offset-1;
4548       if(nbOfNodesForCell<=3)
4549         continue;
4550       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4551       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4552       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4553         cells.push_back(i);
4554       cell2DinS2.clear();
4555     }
4556 }
4557
4558 /*!
4559  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4560  *
4561  * 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.
4562  * 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.
4563  * 
4564  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4565  * This convex envelop is computed using Jarvis march algorithm.
4566  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4567  * 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)
4568  * 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.
4569  *
4570  * \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.
4571  * \sa MEDCouplingUMesh::colinearize2D
4572  */
4573 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4574 {
4575   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4576     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4577   checkFullyDefined();
4578   const double *coords=getCoords()->getConstPointer();
4579   int nbOfCells=getNumberOfCells();
4580   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4581   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4582   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4583   int *workIndexOut=nodalConnecIndexOut->getPointer();
4584   *workIndexOut=0;
4585   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4586   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4587   std::set<INTERP_KERNEL::NormalizedCellType> types;
4588   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4589   isChanged->alloc(0,1);
4590   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4591     {
4592       int pos=nodalConnecOut->getNumberOfTuples();
4593       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4594         isChanged->pushBackSilent(i);
4595       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4596       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4597     }
4598   if(isChanged->empty())
4599     return 0;
4600   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4601   _types=types;
4602   return isChanged.retn();
4603 }
4604
4605 /*!
4606  * This method is \b NOT const because it can modify \a this.
4607  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4608  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4609  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4610  * \b 1 for translation and rotation around point of 'mesh1D'.
4611  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4612  */
4613 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4614 {
4615   checkFullyDefined();
4616   mesh1D->checkFullyDefined();
4617   if(!mesh1D->isContiguous1D())
4618     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4619   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4620     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4621   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4622     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4623   if(mesh1D->getMeshDimension()!=1)
4624     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4625   bool isQuad=false;
4626   if(isPresenceOfQuadratic())
4627     {
4628       if(mesh1D->isFullyQuadratic())
4629         isQuad=true;
4630       else
4631         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4632     }
4633   int oldNbOfNodes(getNumberOfNodes());
4634   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4635   switch(policy)
4636   {
4637     case 0:
4638       {
4639         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4640         break;
4641       }
4642     case 1:
4643       {
4644         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4645         break;
4646       }
4647     default:
4648       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4649   }
4650   setCoords(newCoords);
4651   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad));
4652   updateTime();
4653   return ret.retn();
4654 }
4655
4656 /*!
4657  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4658  * If it is not the case an exception will be thrown.
4659  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4660  * intersection of plane defined by ('origin','vec').
4661  * This method has one in/out parameter : 'cut3DCurve'.
4662  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4663  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4664  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4665  * This method will throw an exception if \a this contains a non linear segment.
4666  */
4667 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4668 {
4669   checkFullyDefined();
4670   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4671     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4672   int ncells=getNumberOfCells();
4673   int nnodes=getNumberOfNodes();
4674   double vec2[3],vec3[3],vec4[3];
4675   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4676   if(normm<1e-6)
4677     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4678   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4679   const int *conn=_nodal_connec->getConstPointer();
4680   const int *connI=_nodal_connec_index->getConstPointer();
4681   const double *coo=_coords->getConstPointer();
4682   std::vector<double> addCoo;
4683   for(int i=0;i<ncells;i++)
4684     {
4685       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4686         {
4687           if(cut3DCurve[i]==-2)
4688             {
4689               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4690               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];
4691               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4692               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4693               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4694                 {
4695                   const double *st2=coo+3*st;
4696                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4697                   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]));
4698                   if(pos>eps && pos<1-eps)
4699                     {
4700                       int nNode=((int)addCoo.size())/3;
4701                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4702                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4703                       cut3DCurve[i]=nnodes+nNode;
4704                     }
4705                 }
4706             }
4707         }
4708       else
4709         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4710     }
4711   if(!addCoo.empty())
4712     {
4713       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4714       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4715       coo2->alloc(newNbOfNodes,3);
4716       double *tmp=coo2->getPointer();
4717       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4718       std::copy(addCoo.begin(),addCoo.end(),tmp);
4719       DataArrayDouble::SetArrayIn(coo2,_coords);
4720     }
4721 }
4722
4723 /*!
4724  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4725  * \param mesh1D is the input 1D mesh used for translation computation.
4726  * \return newCoords new coords filled by this method. 
4727  */
4728 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4729 {
4730   int oldNbOfNodes=getNumberOfNodes();
4731   int nbOf1DCells=mesh1D->getNumberOfCells();
4732   int spaceDim=getSpaceDimension();
4733   DataArrayDouble *ret=DataArrayDouble::New();
4734   std::vector<bool> isQuads;
4735   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4736   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4737   double *retPtr=ret->getPointer();
4738   const double *coords=getCoords()->getConstPointer();
4739   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4740   std::vector<int> v;
4741   std::vector<double> c;
4742   double vec[3];
4743   v.reserve(3);
4744   c.reserve(6);
4745   for(int i=0;i<nbOf1DCells;i++)
4746     {
4747       v.resize(0);
4748       mesh1D->getNodeIdsOfCell(i,v);
4749       c.resize(0);
4750       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4751       mesh1D->getCoordinatesOfNode(v[0],c);
4752       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4753       for(int j=0;j<oldNbOfNodes;j++)
4754         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4755       if(isQuad)
4756         {
4757           c.resize(0);
4758           mesh1D->getCoordinatesOfNode(v[1],c);
4759           mesh1D->getCoordinatesOfNode(v[0],c);
4760           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4761           for(int j=0;j<oldNbOfNodes;j++)
4762             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4763         }
4764     }
4765   ret->copyStringInfoFrom(*getCoords());
4766   return ret;
4767 }
4768
4769 /*!
4770  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4771  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4772  * \return newCoords new coords filled by this method. 
4773  */
4774 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4775 {
4776   if(mesh1D->getSpaceDimension()==2)
4777     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4778   if(mesh1D->getSpaceDimension()==3)
4779     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4780   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4781 }
4782
4783 /*!
4784  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4785  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4786  * \return newCoords new coords filled by this method. 
4787  */
4788 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4789 {
4790   if(isQuad)
4791     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4792   int oldNbOfNodes=getNumberOfNodes();
4793   int nbOf1DCells=mesh1D->getNumberOfCells();
4794   if(nbOf1DCells<2)
4795     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4796   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4797   int nbOfLevsInVec=nbOf1DCells+1;
4798   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4799   double *retPtr=ret->getPointer();
4800   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4801   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4802   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4803   tmp->setCoords(tmp2);
4804   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4805   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4806   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4807   for(int i=1;i<nbOfLevsInVec;i++)
4808     {
4809       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4810       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4811       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4812       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4813       tmp->translate(vec);
4814       double tmp3[2],radius,alpha,alpha0;
4815       const double *p0=i+1<nbOfLevsInVec?begin:third;
4816       const double *p1=i+1<nbOfLevsInVec?end:begin;
4817       const double *p2=i+1<nbOfLevsInVec?third:end;
4818       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4819       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]);
4820       double angle=acos(cosangle/(radius*radius));
4821       tmp->rotate(end,0,angle);
4822       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4823     }
4824   return ret.retn();
4825 }
4826
4827 /*!
4828  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4829  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4830  * \return newCoords new coords filled by this method. 
4831  */
4832 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4833 {
4834   if(isQuad)
4835     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4836   int oldNbOfNodes=getNumberOfNodes();
4837   int nbOf1DCells=mesh1D->getNumberOfCells();
4838   if(nbOf1DCells<2)
4839     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4840   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4841   int nbOfLevsInVec=nbOf1DCells+1;
4842   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4843   double *retPtr=ret->getPointer();
4844   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4845   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4846   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4847   tmp->setCoords(tmp2);
4848   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4849   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4850   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4851   for(int i=1;i<nbOfLevsInVec;i++)
4852     {
4853       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4854       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4855       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4856       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4857       tmp->translate(vec);
4858       double tmp3[2],radius,alpha,alpha0;
4859       const double *p0=i+1<nbOfLevsInVec?begin:third;
4860       const double *p1=i+1<nbOfLevsInVec?end:begin;
4861       const double *p2=i+1<nbOfLevsInVec?third:end;
4862       double vecPlane[3]={
4863         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4864         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4865         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4866       };
4867       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4868       if(norm>1.e-7)
4869         {
4870           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4871           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4872           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4873           double s2=norm2;
4874           double c2=cos(asin(s2));
4875           double m[3][3]={
4876             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4877             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4878             {-vec2[1]*s2, vec2[0]*s2, c2}
4879           };
4880           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]};
4881           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]};
4882           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]};
4883           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4884           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]);
4885           double angle=acos(cosangle/(radius*radius));
4886           tmp->rotate(end,vecPlane,angle);
4887         }
4888       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4889     }
4890   return ret.retn();
4891 }
4892
4893 /*!
4894  * This method is private because not easy to use for end user. This method is const contrary to
4895  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4896  * the coords sorted slice by slice.
4897  * \param isQuad specifies presence of quadratic cells.
4898  */
4899 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4900 {
4901   int nbOf1DCells(getNumberOfNodes()/nbOfNodesOf1Lev-1);
4902   int nbOf2DCells(getNumberOfCells());
4903   int nbOf3DCells(nbOf2DCells*nbOf1DCells);
4904   MEDCouplingUMesh *ret(MEDCouplingUMesh::New("Extruded",getMeshDimension()+1));
4905   const int *conn(_nodal_connec->begin()),*connI(_nodal_connec_index->begin());
4906   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()),newConnI(DataArrayInt::New());
4907   newConnI->alloc(nbOf3DCells+1,1);
4908   int *newConnIPtr(newConnI->getPointer());
4909   *newConnIPtr++=0;
4910   std::vector<int> newc;
4911   for(int j=0;j<nbOf2DCells;j++)
4912     {
4913       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4914       *newConnIPtr++=(int)newc.size();
4915     }
4916   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4917   int *newConnPtr(newConn->getPointer());
4918   int deltaPerLev(isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev);
4919   newConnIPtr=newConnI->getPointer();
4920   for(int iz=0;iz<nbOf1DCells;iz++)
4921     {
4922       if(iz!=0)
4923         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4924       const int *posOfTypeOfCell(newConnIPtr);
4925       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4926         {
4927           int icell((int)(iter-newc.begin()));//std::distance unfortunately cannot been called here in C++98
4928           if(icell!=*posOfTypeOfCell)
4929             {
4930               if(*iter!=-1)
4931                 *newConnPtr=(*iter)+iz*deltaPerLev;
4932               else
4933                 *newConnPtr=-1;
4934             }
4935           else
4936             {
4937               *newConnPtr=*iter;
4938               posOfTypeOfCell++;
4939             }
4940         }
4941     }
4942   ret->setConnectivity(newConn,newConnI,true);
4943   ret->setCoords(getCoords());
4944   return ret;
4945 }
4946
4947 /*!
4948  * Checks if \a this mesh is constituted by only quadratic cells.
4949  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4950  *  \throw If the coordinates array is not set.
4951  *  \throw If the nodal connectivity of cells is not defined.
4952  */
4953 bool MEDCouplingUMesh::isFullyQuadratic() const
4954 {
4955   checkFullyDefined();
4956   bool ret=true;
4957   int nbOfCells=getNumberOfCells();
4958   for(int i=0;i<nbOfCells && ret;i++)
4959     {
4960       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4961       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4962       ret=cm.isQuadratic();
4963     }
4964   return ret;
4965 }
4966
4967 /*!
4968  * Checks if \a this mesh includes any quadratic cell.
4969  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4970  *  \throw If the coordinates array is not set.
4971  *  \throw If the nodal connectivity of cells is not defined.
4972  */
4973 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4974 {
4975   checkFullyDefined();
4976   bool ret=false;
4977   int nbOfCells=getNumberOfCells();
4978   for(int i=0;i<nbOfCells && !ret;i++)
4979     {
4980       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4981       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4982       ret=cm.isQuadratic();
4983     }
4984   return ret;
4985 }
4986
4987 /*!
4988  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4989  * this mesh, it remains unchanged.
4990  *  \throw If the coordinates array is not set.
4991  *  \throw If the nodal connectivity of cells is not defined.
4992  */
4993 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4994 {
4995   checkFullyDefined();
4996   int nbOfCells=getNumberOfCells();
4997   int delta=0;
4998   const int *iciptr=_nodal_connec_index->getConstPointer();
4999   for(int i=0;i<nbOfCells;i++)
5000     {
5001       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
5002       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5003       if(cm.isQuadratic())
5004         {
5005           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5006           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5007           if(!cml.isDynamic())
5008             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
5009           else
5010             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
5011         }
5012     }
5013   if(delta==0)
5014     return ;
5015   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5016   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5017   const int *icptr=_nodal_connec->getConstPointer();
5018   newConn->alloc(getMeshLength()-delta,1);
5019   newConnI->alloc(nbOfCells+1,1);
5020   int *ocptr=newConn->getPointer();
5021   int *ociptr=newConnI->getPointer();
5022   *ociptr=0;
5023   _types.clear();
5024   for(int i=0;i<nbOfCells;i++,ociptr++)
5025     {
5026       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
5027       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
5028       if(!cm.isQuadratic())
5029         {
5030           _types.insert(type);
5031           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
5032           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
5033         }
5034       else
5035         {
5036           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
5037           _types.insert(typel);
5038           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
5039           int newNbOfNodes=cml.getNumberOfNodes();
5040           if(cml.isDynamic())
5041             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
5042           *ocptr++=(int)typel;
5043           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
5044           ociptr[1]=ociptr[0]+newNbOfNodes+1;
5045         }
5046     }
5047   setConnectivity(newConn,newConnI,false);
5048 }
5049
5050 /*!
5051  * This method converts all linear cell in \a this to quadratic one.
5052  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
5053  * 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)
5054  * 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.
5055  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
5056  * end of the existing coordinates.
5057  * 
5058  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
5059  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
5060  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5061  * 
5062  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
5063  *
5064  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
5065  */
5066 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
5067 {
5068   DataArrayInt *conn=0,*connI=0;
5069   DataArrayDouble *coords=0;
5070   std::set<INTERP_KERNEL::NormalizedCellType> types;
5071   checkFullyDefined();
5072   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
5073   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
5074   int meshDim=getMeshDimension();
5075   switch(conversionType)
5076   {
5077     case 0:
5078       switch(meshDim)
5079       {
5080         case 1:
5081           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
5082           connSafe=conn; connISafe=connI; coordsSafe=coords;
5083           break;
5084         case 2:
5085           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
5086           connSafe=conn; connISafe=connI; coordsSafe=coords;
5087           break;
5088         case 3:
5089           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
5090           connSafe=conn; connISafe=connI; coordsSafe=coords;
5091           break;
5092         default:
5093           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
5094       }
5095       break;
5096         case 1:
5097           {
5098             switch(meshDim)
5099             {
5100               case 1:
5101                 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
5102                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5103                 break;
5104               case 2:
5105                 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
5106                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5107                 break;
5108               case 3:
5109                 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
5110                 connSafe=conn; connISafe=connI; coordsSafe=coords;
5111                 break;
5112               default:
5113                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5114             }
5115             break;
5116           }
5117         default:
5118           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5119   }
5120   setConnectivity(connSafe,connISafe,false);
5121   _types=types;
5122   setCoords(coordsSafe);
5123   return ret.retn();
5124 }
5125
5126 #if 0
5127 /*!
5128  * This method only works if \a this has spaceDimension equal to 2 and meshDimension also equal to 2.
5129  * This method allows to modify connectivity of cells in \a this that shares some edges in \a edgeIdsToBeSplit.
5130  * The nodes to be added in those 2D cells are defined by the pair of \a  nodeIdsToAdd and \a nodeIdsIndexToAdd.
5131  * Length of \a nodeIdsIndexToAdd is expected to equal to length of \a edgeIdsToBeSplit + 1.
5132  * The node ids in \a nodeIdsToAdd should be valid. Those nodes have to be sorted exactly following exactly the direction of the edge.
5133  * This method can be seen as the opposite method of colinearize2D.
5134  * 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
5135  * to avoid to modify the numbering of existing nodes.
5136  *
5137  * \param [in] nodeIdsToAdd - the list of node ids to be added (\a nodeIdsIndexToAdd array allows to walk on this array)
5138  * \param [in] nodeIdsIndexToAdd - the entry point of \a nodeIdsToAdd to point to the corresponding nodes to be added.
5139  * \param [in] mesh1Desc - 1st output of buildDescendingConnectivity2 on \a this.
5140  * \param [in] desc - 2nd output of buildDescendingConnectivity2 on \a this.
5141  * \param [in] descI - 3rd output of buildDescendingConnectivity2 on \a this.
5142  * \param [in] revDesc - 4th output of buildDescendingConnectivity2 on \a this.
5143  * \param [in] revDescI - 5th output of buildDescendingConnectivity2 on \a this.
5144  *
5145  * \sa buildDescendingConnectivity2
5146  */
5147 void MEDCouplingUMesh::splitSomeEdgesOf2DMesh(const DataArrayInt *nodeIdsToAdd, const DataArrayInt *nodeIdsIndexToAdd, const DataArrayInt *edgeIdsToBeSplit,
5148                                               const MEDCouplingUMesh *mesh1Desc, const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *revDesc, const DataArrayInt *revDescI)
5149 {
5150   if(!nodeIdsToAdd || !nodeIdsIndexToAdd || !edgeIdsToBeSplit || !mesh1Desc || !desc || !descI || !revDesc || !revDescI)
5151     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : input pointers must be not NULL !");
5152   nodeIdsToAdd->checkAllocated(); nodeIdsIndexToAdd->checkAllocated(); edgeIdsToBeSplit->checkAllocated(); desc->checkAllocated(); descI->checkAllocated(); revDesc->checkAllocated(); revDescI->checkAllocated();
5153   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
5154     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : this must have spacedim=meshdim=2 !");
5155   if(mesh1Desc->getSpaceDimension()!=2 || mesh1Desc->getMeshDimension()!=1)
5156     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitSomeEdgesOf2DMesh : mesh1Desc must be the explosion of this with spaceDim=2 and meshDim = 1 !");
5157   //DataArrayInt *out0(0),*outi0(0);
5158   //MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
5159   //MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0s(out0),outi0s(outi0);
5160   //out0s=out0s->buildUnique(); out0s->sort(true);
5161 }
5162 #endif
5163
5164 /*!
5165  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5166  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5167  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5168  */
5169 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5170 {
5171   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5172   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5173   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5174   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5175   int nbOfCells=getNumberOfCells();
5176   int nbOfNodes=getNumberOfNodes();
5177   const int *cPtr=_nodal_connec->getConstPointer();
5178   const int *icPtr=_nodal_connec_index->getConstPointer();
5179   int lastVal=0,offset=nbOfNodes;
5180   for(int i=0;i<nbOfCells;i++,icPtr++)
5181     {
5182       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5183       if(type==INTERP_KERNEL::NORM_SEG2)
5184         {
5185           types.insert(INTERP_KERNEL::NORM_SEG3);
5186           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5187           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5188           newConn->pushBackSilent(offset++);
5189           lastVal+=4;
5190           newConnI->pushBackSilent(lastVal);
5191           ret->pushBackSilent(i);
5192         }
5193       else
5194         {
5195           types.insert(type);
5196           lastVal+=(icPtr[1]-icPtr[0]);
5197           newConnI->pushBackSilent(lastVal);
5198           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5199         }
5200     }
5201   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5202   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5203   return ret.retn();
5204 }
5205
5206 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
5207 {
5208   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5210   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5211   //
5212   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5213   DataArrayInt *conn1D=0,*conn1DI=0;
5214   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5215   DataArrayDouble *coordsTmp=0;
5216   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5217   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5218   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5219   const int *c1DPtr=conn1D->begin();
5220   const int *c1DIPtr=conn1DI->begin();
5221   int nbOfCells=getNumberOfCells();
5222   const int *cPtr=_nodal_connec->getConstPointer();
5223   const int *icPtr=_nodal_connec_index->getConstPointer();
5224   int lastVal=0;
5225   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5226     {
5227       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5228       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5229       if(!cm.isQuadratic())
5230         {
5231           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5232           types.insert(typ2); newConn->pushBackSilent(typ2);
5233           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5234           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5235             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5236           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5237           newConnI->pushBackSilent(lastVal);
5238           ret->pushBackSilent(i);
5239         }
5240       else
5241         {
5242           types.insert(typ);
5243           lastVal+=(icPtr[1]-icPtr[0]);
5244           newConnI->pushBackSilent(lastVal);
5245           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5246         }
5247     }
5248   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5249   return ret.retn();
5250 }
5251
5252 /*!
5253  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5254  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5255  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5256  */
5257 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5258 {
5259   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5260   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5261   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5262 }
5263
5264 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5265 {
5266   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5267   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5268   //
5269   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5270   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5271   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5272   //
5273   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5274   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5275   DataArrayInt *conn1D=0,*conn1DI=0;
5276   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5277   DataArrayDouble *coordsTmp=0;
5278   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5279   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5280   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5281   const int *c1DPtr=conn1D->begin();
5282   const int *c1DIPtr=conn1DI->begin();
5283   int nbOfCells=getNumberOfCells();
5284   const int *cPtr=_nodal_connec->getConstPointer();
5285   const int *icPtr=_nodal_connec_index->getConstPointer();
5286   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5287   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5288     {
5289       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5290       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5291       if(!cm.isQuadratic())
5292         {
5293           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5294           types.insert(typ2); newConn->pushBackSilent(typ2);
5295           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5296           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5297             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5298           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5299           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5300           newConnI->pushBackSilent(lastVal);
5301           ret->pushBackSilent(i);
5302         }
5303       else
5304         {
5305           types.insert(typ);
5306           lastVal+=(icPtr[1]-icPtr[0]);
5307           newConnI->pushBackSilent(lastVal);
5308           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5309         }
5310     }
5311   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5312   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5313   return ret.retn();
5314 }
5315
5316 /*!
5317  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5318  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5319  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5320  */
5321 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5322 {
5323   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5324   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5325   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5326 }
5327
5328 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5329 {
5330   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5331   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5332   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5333   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5334   //
5335   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5336   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5337   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5338   //
5339   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5340   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5341   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5342   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5343   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5344   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5345   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5346   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5347   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5348   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5349   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5350   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5351   int nbOfCells=getNumberOfCells();
5352   const int *cPtr=_nodal_connec->getConstPointer();
5353   const int *icPtr=_nodal_connec_index->getConstPointer();
5354   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5355   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5356     {
5357       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5358       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5359       if(!cm.isQuadratic())
5360         {
5361           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5362           if(typ2==INTERP_KERNEL::NORM_ERROR)
5363             {
5364               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5365               throw INTERP_KERNEL::Exception(oss.str().c_str());
5366             }
5367           types.insert(typ2); newConn->pushBackSilent(typ2);
5368           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5369           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5370             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5371           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5372             {
5373               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5374               int tmpPos=newConn->getNumberOfTuples();
5375               newConn->pushBackSilent(nodeId2);
5376               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5377             }
5378           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5379           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5380           newConnI->pushBackSilent(lastVal);
5381           ret->pushBackSilent(i);
5382         }
5383       else
5384         {
5385           types.insert(typ);
5386           lastVal+=(icPtr[1]-icPtr[0]);
5387           newConnI->pushBackSilent(lastVal);
5388           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5389         }
5390     }
5391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5392   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5393   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5394   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5395   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5396   int *c=newConn->getPointer();
5397   const int *cI(newConnI->begin());
5398   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5399     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5400   offset=coordsTmp2Safe->getNumberOfTuples();
5401   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5402     c[cI[(*elt)+1]-1]+=offset;
5403   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5404   return ret.retn();
5405 }
5406
5407 /*!
5408  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5409  * so that the number of cells remains the same. Quadratic faces are converted to
5410  * polygons. This method works only for 2D meshes in
5411  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5412  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5413  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5414  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5415  *         a polylinized edge constituting the input polygon.
5416  *  \throw If the coordinates array is not set.
5417  *  \throw If the nodal connectivity of cells is not defined.
5418  *  \throw If \a this->getMeshDimension() != 2.
5419  *  \throw If \a this->getSpaceDimension() != 2.
5420  */
5421 void MEDCouplingUMesh::tessellate2D(double eps)
5422 {
5423   checkFullyDefined();
5424   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5425     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5426   double epsa=fabs(eps);
5427   if(epsa<std::numeric_limits<double>::min())
5428     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 !");
5429   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5430   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5432   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5433   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5434   revDesc1=0; revDescIndx1=0;
5435   mDesc->tessellate2DCurve(eps);
5436   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5437   setCoords(mDesc->getCoords());
5438 }
5439
5440 /*!
5441  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5442  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5443  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5444  *         a sub-divided edge.
5445  *  \throw If the coordinates array is not set.
5446  *  \throw If the nodal connectivity of cells is not defined.
5447  *  \throw If \a this->getMeshDimension() != 1.
5448  *  \throw If \a this->getSpaceDimension() != 2.
5449  */
5450 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5451 {
5452   checkFullyDefined();
5453   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5454     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5455   double epsa=fabs(eps);
5456   if(epsa<std::numeric_limits<double>::min())
5457     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 !");
5458   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5459   int nbCells=getNumberOfCells();
5460   int nbNodes=getNumberOfNodes();
5461   const int *conn=_nodal_connec->getConstPointer();
5462   const int *connI=_nodal_connec_index->getConstPointer();
5463   const double *coords=_coords->getConstPointer();
5464   std::vector<double> addCoo;
5465   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5466   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5467   newConnI->alloc(nbCells+1,1);
5468   int *newConnIPtr=newConnI->getPointer();
5469   *newConnIPtr=0;
5470   int tmp1[3];
5471   INTERP_KERNEL::Node *tmp2[3];
5472   std::set<INTERP_KERNEL::NormalizedCellType> types;
5473   for(int i=0;i<nbCells;i++,newConnIPtr++)
5474     {
5475       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5476       if(cm.isQuadratic())
5477         {//assert(connI[i+1]-connI[i]-1==3)
5478           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5479           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5480           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5481           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5482           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5483           if(eac)
5484             {
5485               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5486               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5487               delete eac;
5488               newConnIPtr[1]=(int)newConn.size();
5489             }
5490           else
5491             {
5492               types.insert(INTERP_KERNEL::NORM_SEG2);
5493               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5494               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5495               newConnIPtr[1]=newConnIPtr[0]+3;
5496             }
5497         }
5498       else
5499         {
5500           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5501           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5502           newConnIPtr[1]=newConnIPtr[0]+3;
5503         }
5504     }
5505   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5506     return ;
5507   _types=types;
5508   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5509   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5510   newConnArr->alloc((int)newConn.size(),1);
5511   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5512   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5513   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5514   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5515   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5516   std::copy(addCoo.begin(),addCoo.end(),work);
5517   DataArrayDouble::SetArrayIn(newCoords,_coords);
5518   updateTime();
5519 }
5520
5521 /*!
5522  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5523  * In addition, returns an array mapping new cells to old ones. <br>
5524  * This method typically increases the number of cells in \a this mesh
5525  * but the number of nodes remains \b unchanged.
5526  * That's why the 3D splitting policies
5527  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5528  *  \param [in] policy - specifies a pattern used for splitting.
5529  * The semantic of \a policy is:
5530  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5531  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5532  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5533  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only - see INTERP_KERNEL::SplittingPolicy for an image).
5534  *
5535  *
5536  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5537  *          an id of old cell producing it. The caller is to delete this array using
5538  *         decrRef() as it is no more needed.
5539  *
5540  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5541  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5542  *          and \a this->getMeshDimension() != 3. 
5543  *  \throw If \a policy is not one of the four discussed above.
5544  *  \throw If the nodal connectivity of cells is not defined.
5545  * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5546  */
5547 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5548 {
5549   switch(policy)
5550   {
5551     case 0:
5552       return simplexizePol0();
5553     case 1:
5554       return simplexizePol1();
5555     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5556         return simplexizePlanarFace5();
5557     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5558         return simplexizePlanarFace6();
5559     default:
5560       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)");
5561   }
5562 }
5563
5564 /*!
5565  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5566  * - 1D: INTERP_KERNEL::NORM_SEG2
5567  * - 2D: INTERP_KERNEL::NORM_TRI3
5568  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5569  *
5570  * This method is useful for users that need to use P1 field services as
5571  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5572  * All these methods need mesh support containing only simplex cells.
5573  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5574  *  \throw If the coordinates array is not set.
5575  *  \throw If the nodal connectivity of cells is not defined.
5576  *  \throw If \a this->getMeshDimension() < 1.
5577  */
5578 bool MEDCouplingUMesh::areOnlySimplexCells() const
5579 {
5580   checkFullyDefined();
5581   int mdim=getMeshDimension();
5582   if(mdim<1 || mdim>3)
5583     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5584   int nbCells=getNumberOfCells();
5585   const int *conn=_nodal_connec->getConstPointer();
5586   const int *connI=_nodal_connec_index->getConstPointer();
5587   for(int i=0;i<nbCells;i++)
5588     {
5589       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5590       if(!cm.isSimplex())
5591         return false;
5592     }
5593   return true;
5594 }
5595
5596 /*!
5597  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5598  */
5599 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5600 {
5601   checkConnectivityFullyDefined();
5602   if(getMeshDimension()!=2)
5603     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5604   int nbOfCells=getNumberOfCells();
5605   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5606   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5607   ret->alloc(nbOfCells+nbOfCutCells,1);
5608   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5609   int *retPt=ret->getPointer();
5610   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5611   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5612   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5613   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5614   int *pt=newConn->getPointer();
5615   int *ptI=newConnI->getPointer();
5616   ptI[0]=0;
5617   const int *oldc=_nodal_connec->getConstPointer();
5618   const int *ci=_nodal_connec_index->getConstPointer();
5619   for(int i=0;i<nbOfCells;i++,ci++)
5620     {
5621       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5622         {
5623           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5624             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5625           pt=std::copy(tmp,tmp+8,pt);
5626           ptI[1]=ptI[0]+4;
5627           ptI[2]=ptI[0]+8;
5628           *retPt++=i;
5629           *retPt++=i;
5630           ptI+=2;
5631         }
5632       else
5633         {
5634           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5635           ptI[1]=ptI[0]+ci[1]-ci[0];
5636           ptI++;
5637           *retPt++=i;
5638         }
5639     }
5640   _nodal_connec->decrRef();
5641   _nodal_connec=newConn.retn();
5642   _nodal_connec_index->decrRef();
5643   _nodal_connec_index=newConnI.retn();
5644   computeTypes();
5645   updateTime();
5646   return ret.retn();
5647 }
5648
5649 /*!
5650  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5651  */
5652 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5653 {
5654   checkConnectivityFullyDefined();
5655   if(getMeshDimension()!=2)
5656     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5657   int nbOfCells=getNumberOfCells();
5658   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5659   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5660   ret->alloc(nbOfCells+nbOfCutCells,1);
5661   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5662   int *retPt=ret->getPointer();
5663   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5664   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5665   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5666   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5667   int *pt=newConn->getPointer();
5668   int *ptI=newConnI->getPointer();
5669   ptI[0]=0;
5670   const int *oldc=_nodal_connec->getConstPointer();
5671   const int *ci=_nodal_connec_index->getConstPointer();
5672   for(int i=0;i<nbOfCells;i++,ci++)
5673     {
5674       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5675         {
5676           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5677             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5678           pt=std::copy(tmp,tmp+8,pt);
5679           ptI[1]=ptI[0]+4;
5680           ptI[2]=ptI[0]+8;
5681           *retPt++=i;
5682           *retPt++=i;
5683           ptI+=2;
5684         }
5685       else
5686         {
5687           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5688           ptI[1]=ptI[0]+ci[1]-ci[0];
5689           ptI++;
5690           *retPt++=i;
5691         }
5692     }
5693   _nodal_connec->decrRef();
5694   _nodal_connec=newConn.retn();
5695   _nodal_connec_index->decrRef();
5696   _nodal_connec_index=newConnI.retn();
5697   computeTypes();
5698   updateTime();
5699   return ret.retn();
5700 }
5701
5702 /*!
5703  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5704  */
5705 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5706 {
5707   checkConnectivityFullyDefined();
5708   if(getMeshDimension()!=3)
5709     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5710   int nbOfCells=getNumberOfCells();
5711   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5712   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5713   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5714   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5715   int *retPt=ret->getPointer();
5716   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5717   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5718   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5719   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5720   int *pt=newConn->getPointer();
5721   int *ptI=newConnI->getPointer();
5722   ptI[0]=0;
5723   const int *oldc=_nodal_connec->getConstPointer();
5724   const int *ci=_nodal_connec_index->getConstPointer();
5725   for(int i=0;i<nbOfCells;i++,ci++)
5726     {
5727       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5728         {
5729           for(int j=0;j<5;j++,pt+=5,ptI++)
5730             {
5731               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5732               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];
5733               *retPt++=i;
5734               ptI[1]=ptI[0]+5;
5735             }
5736         }
5737       else
5738         {
5739           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5740           ptI[1]=ptI[0]+ci[1]-ci[0];
5741           ptI++;
5742           *retPt++=i;
5743         }
5744     }
5745   _nodal_connec->decrRef();
5746   _nodal_connec=newConn.retn();
5747   _nodal_connec_index->decrRef();
5748   _nodal_connec_index=newConnI.retn();
5749   computeTypes();
5750   updateTime();
5751   return ret.retn();
5752 }
5753
5754 /*!
5755  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5756  */
5757 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5758 {
5759   checkConnectivityFullyDefined();
5760   if(getMeshDimension()!=3)
5761     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5762   int nbOfCells=getNumberOfCells();
5763   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5764   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5765   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5766   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5767   int *retPt=ret->getPointer();
5768   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5769   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5770   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5771   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5772   int *pt=newConn->getPointer();
5773   int *ptI=newConnI->getPointer();
5774   ptI[0]=0;
5775   const int *oldc=_nodal_connec->getConstPointer();
5776   const int *ci=_nodal_connec_index->getConstPointer();
5777   for(int i=0;i<nbOfCells;i++,ci++)
5778     {
5779       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5780         {
5781           for(int j=0;j<6;j++,pt+=5,ptI++)
5782             {
5783               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5784               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];
5785               *retPt++=i;
5786               ptI[1]=ptI[0]+5;
5787             }
5788         }
5789       else
5790         {
5791           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5792           ptI[1]=ptI[0]+ci[1]-ci[0];
5793           ptI++;
5794           *retPt++=i;
5795         }
5796     }
5797   _nodal_connec->decrRef();
5798   _nodal_connec=newConn.retn();
5799   _nodal_connec_index->decrRef();
5800   _nodal_connec_index=newConnI.retn();
5801   computeTypes();
5802   updateTime();
5803   return ret.retn();
5804 }
5805
5806 /*!
5807  * 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.
5808  * This method completly ignore coordinates.
5809  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5810  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5811  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5812  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5813  */
5814 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5815 {
5816   checkFullyDefined();
5817   if(getMeshDimension()!=2)
5818     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5819   int nbOfCells=getNumberOfCells();
5820   int *connI=_nodal_connec_index->getPointer();
5821   int newConnLgth=0;
5822   for(int i=0;i<nbOfCells;i++,connI++)
5823     {
5824       int offset=descIndex[i];
5825       int nbOfEdges=descIndex[i+1]-offset;
5826       //
5827       bool ddirect=desc[offset+nbOfEdges-1]>0;
5828       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5829       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5830       for(int j=0;j<nbOfEdges;j++)
5831         {
5832           bool direct=desc[offset+j]>0;
5833           int edgeId=std::abs(desc[offset+j])-1;
5834           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5835             {
5836               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5837               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5838               int ref2=direct?id1:id2;
5839               if(ref==ref2)
5840                 {
5841                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5842                   newConnLgth+=nbOfSubNodes-1;
5843                   ref=direct?id2:id1;
5844                 }
5845               else
5846                 {
5847                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5848                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5849                 }
5850             }
5851           else
5852             {
5853               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5854             }
5855         }
5856       newConnLgth++;//+1 is for cell type
5857       connI[1]=newConnLgth;
5858     }
5859   //
5860   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5861   newConn->alloc(newConnLgth,1);
5862   int *work=newConn->getPointer();
5863   for(int i=0;i<nbOfCells;i++)
5864     {
5865       *work++=INTERP_KERNEL::NORM_POLYGON;
5866       int offset=descIndex[i];
5867       int nbOfEdges=descIndex[i+1]-offset;
5868       for(int j=0;j<nbOfEdges;j++)
5869         {
5870           bool direct=desc[offset+j]>0;
5871           int edgeId=std::abs(desc[offset+j])-1;
5872           if(direct)
5873             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5874           else
5875             {
5876               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5877               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5878               work=std::copy(it,it+nbOfSubNodes-1,work);
5879             }
5880         }
5881     }
5882   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5883   _types.clear();
5884   if(nbOfCells>0)
5885     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5886 }
5887
5888 /*!
5889  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5890  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5891  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5892  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5893  * so it can be useful to call mergeNodes() before calling this method.
5894  *  \throw If \a this->getMeshDimension() <= 1.
5895  *  \throw If the coordinates array is not set.
5896  *  \throw If the nodal connectivity of cells is not defined.
5897  */
5898 void MEDCouplingUMesh::convertDegeneratedCells()
5899 {
5900   checkFullyDefined();
5901   if(getMeshDimension()<=1)
5902     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5903   int nbOfCells=getNumberOfCells();
5904   if(nbOfCells<1)
5905     return ;
5906   int initMeshLgth=getMeshLength();
5907   int *conn=_nodal_connec->getPointer();
5908   int *index=_nodal_connec_index->getPointer();
5909   int posOfCurCell=0;
5910   int newPos=0;
5911   int lgthOfCurCell;
5912   for(int i=0;i<nbOfCells;i++)
5913     {
5914       lgthOfCurCell=index[i+1]-posOfCurCell;
5915       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5916       int newLgth;
5917       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5918                                                                                                      conn+newPos+1,newLgth);
5919       conn[newPos]=newType;
5920       newPos+=newLgth+1;
5921       posOfCurCell=index[i+1];
5922       index[i+1]=newPos;
5923     }
5924   if(newPos!=initMeshLgth)
5925     _nodal_connec->reAlloc(newPos);
5926   computeTypes();
5927 }
5928
5929 /*!
5930  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5931  * A cell is considered to be oriented correctly if an angle between its
5932  * normal vector and a given vector is less than \c PI / \c 2.
5933  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5934  *         cells. 
5935  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5936  *         checked.
5937  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5938  *         is not cleared before filling in.
5939  *  \throw If \a this->getMeshDimension() != 2.
5940  *  \throw If \a this->getSpaceDimension() != 3.
5941  *
5942  *  \if ENABLE_EXAMPLES
5943  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5944  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5945  *  \endif
5946  */
5947 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5948 {
5949   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5950     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5951   int nbOfCells=getNumberOfCells();
5952   const int *conn=_nodal_connec->getConstPointer();
5953   const int *connI=_nodal_connec_index->getConstPointer();
5954   const double *coordsPtr=_coords->getConstPointer();
5955   for(int i=0;i<nbOfCells;i++)
5956     {
5957       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5958       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5959         {
5960           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5961           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5962             cells.push_back(i);
5963         }
5964     }
5965 }
5966
5967 /*!
5968  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5969  * considered to be oriented correctly if an angle between its normal vector and a
5970  * given vector is less than \c PI / \c 2. 
5971  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5972  *         cells. 
5973  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5974  *         checked.
5975  *  \throw If \a this->getMeshDimension() != 2.
5976  *  \throw If \a this->getSpaceDimension() != 3.
5977  *
5978  *  \if ENABLE_EXAMPLES
5979  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5980  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5981  *  \endif
5982  *
5983  *  \sa changeOrientationOfCells
5984  */
5985 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5986 {
5987   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5988     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5989   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
5990   const int *connI(_nodal_connec_index->getConstPointer());
5991   const double *coordsPtr(_coords->getConstPointer());
5992   bool isModified(false);
5993   for(int i=0;i<nbOfCells;i++)
5994     {
5995       INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5996       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5997         {
5998           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
5999           bool isQuadratic(cm.isQuadratic());
6000           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6001             {
6002               isModified=true;
6003               cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6004             }
6005         }
6006     }
6007   if(isModified)
6008     _nodal_connec->declareAsNew();
6009   updateTime();
6010 }
6011
6012 /*!
6013  * This method change the orientation of cells in \a this without any consideration of coordinates. Only connectivity is impacted.
6014  *
6015  * \sa orientCorrectly2DCells
6016  */
6017 void MEDCouplingUMesh::changeOrientationOfCells()
6018 {
6019   int mdim(getMeshDimension());
6020   if(mdim!=2 && mdim!=1)
6021     throw INTERP_KERNEL::Exception("Invalid mesh to apply changeOrientationOfCells on it : must be meshDim==2 or meshDim==1 !");
6022   int nbOfCells(getNumberOfCells()),*conn(_nodal_connec->getPointer());
6023   const int *connI(_nodal_connec_index->getConstPointer());
6024   if(mdim==2)
6025     {//2D
6026       for(int i=0;i<nbOfCells;i++)
6027         {
6028           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6029           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6030           cm.changeOrientationOf2D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6031         }
6032     }
6033   else
6034     {//1D
6035       for(int i=0;i<nbOfCells;i++)
6036         {
6037           INTERP_KERNEL::NormalizedCellType type((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6038           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(type));
6039           cm.changeOrientationOf1D(conn+connI[i]+1,(unsigned int)(connI[i+1]-connI[i]-1));
6040         }
6041     }
6042 }
6043
6044 /*!
6045  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
6046  * oriented facets. The normal vector of the facet should point out of the cell.
6047  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
6048  *         is not cleared before filling in.
6049  *  \throw If \a this->getMeshDimension() != 3.
6050  *  \throw If \a this->getSpaceDimension() != 3.
6051  *  \throw If the coordinates array is not set.
6052  *  \throw If the nodal connectivity of cells is not defined.
6053  *
6054  *  \if ENABLE_EXAMPLES
6055  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6056  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6057  *  \endif
6058  */
6059 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
6060 {
6061   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6062     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
6063   int nbOfCells=getNumberOfCells();
6064   const int *conn=_nodal_connec->getConstPointer();
6065   const int *connI=_nodal_connec_index->getConstPointer();
6066   const double *coordsPtr=_coords->getConstPointer();
6067   for(int i=0;i<nbOfCells;i++)
6068     {
6069       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6070       if(type==INTERP_KERNEL::NORM_POLYHED)
6071         {
6072           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6073             cells.push_back(i);
6074         }
6075     }
6076 }
6077
6078 /*!
6079  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
6080  * out of the cell. 
6081  *  \throw If \a this->getMeshDimension() != 3.
6082  *  \throw If \a this->getSpaceDimension() != 3.
6083  *  \throw If the coordinates array is not set.
6084  *  \throw If the nodal connectivity of cells is not defined.
6085  *  \throw If the reparation fails.
6086  *
6087  *  \if ENABLE_EXAMPLES
6088  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
6089  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
6090  *  \endif
6091  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6092  */
6093 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
6094 {
6095   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6096     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
6097   int nbOfCells=getNumberOfCells();
6098   int *conn=_nodal_connec->getPointer();
6099   const int *connI=_nodal_connec_index->getConstPointer();
6100   const double *coordsPtr=_coords->getConstPointer();
6101   for(int i=0;i<nbOfCells;i++)
6102     {
6103       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6104       if(type==INTERP_KERNEL::NORM_POLYHED)
6105         {
6106           try
6107           {
6108               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6109                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6110           }
6111           catch(INTERP_KERNEL::Exception& e)
6112           {
6113               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
6114               throw INTERP_KERNEL::Exception(oss.str().c_str());
6115           }
6116         }
6117     }
6118   updateTime();
6119 }
6120
6121 /*!
6122  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
6123  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
6124  * according to which the first facet of the cell should be oriented to have the normal vector
6125  * pointing out of cell.
6126  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
6127  *         cells. The caller is to delete this array using decrRef() as it is no more
6128  *         needed. 
6129  *  \throw If \a this->getMeshDimension() != 3.
6130  *  \throw If \a this->getSpaceDimension() != 3.
6131  *  \throw If the coordinates array is not set.
6132  *  \throw If the nodal connectivity of cells is not defined.
6133  *
6134  *  \if ENABLE_EXAMPLES
6135  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
6136  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
6137  *  \endif
6138  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
6139  */
6140 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
6141 {
6142   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
6143   if(getMeshDimension()!=3)
6144     throw INTERP_KERNEL::Exception(msg);
6145   int spaceDim=getSpaceDimension();
6146   if(spaceDim!=3)
6147     throw INTERP_KERNEL::Exception(msg);
6148   //
6149   int nbOfCells=getNumberOfCells();
6150   int *conn=_nodal_connec->getPointer();
6151   const int *connI=_nodal_connec_index->getConstPointer();
6152   const double *coo=getCoords()->getConstPointer();
6153   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
6154   for(int i=0;i<nbOfCells;i++)
6155     {
6156       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
6157       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
6158         {
6159           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
6160             {
6161               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6162               cells->pushBackSilent(i);
6163             }
6164         }
6165     }
6166   return cells.retn();
6167 }
6168
6169 /*!
6170  * This method is a faster method to correct orientation of all 3D cells in \a this.
6171  * 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.
6172  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6173  * 
6174  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6175  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
6176  */
6177 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6178 {
6179   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6180     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6181   int nbOfCells=getNumberOfCells();
6182   int *conn=_nodal_connec->getPointer();
6183   const int *connI=_nodal_connec_index->getConstPointer();
6184   const double *coordsPtr=_coords->getConstPointer();
6185   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6186   for(int i=0;i<nbOfCells;i++)
6187     {
6188       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6189       switch(type)
6190       {
6191         case INTERP_KERNEL::NORM_TETRA4:
6192           {
6193             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6194               {
6195                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6196                 ret->pushBackSilent(i);
6197               }
6198             break;
6199           }
6200         case INTERP_KERNEL::NORM_PYRA5:
6201           {
6202             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6203               {
6204                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6205                 ret->pushBackSilent(i);
6206               }
6207             break;
6208           }
6209         case INTERP_KERNEL::NORM_PENTA6:
6210         case INTERP_KERNEL::NORM_HEXA8:
6211         case INTERP_KERNEL::NORM_HEXGP12:
6212           {
6213             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6214               {
6215                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6216                 ret->pushBackSilent(i);
6217               }
6218             break;
6219           }
6220         case INTERP_KERNEL::NORM_POLYHED:
6221           {
6222             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6223               {
6224                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6225                 ret->pushBackSilent(i);
6226               }
6227             break;
6228           }
6229         default:
6230           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 !");
6231       }
6232     }
6233   updateTime();
6234   return ret.retn();
6235 }
6236
6237 /*!
6238  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6239  * If it is not the case an exception will be thrown.
6240  * This method is fast because the first cell of \a this is used to compute the plane.
6241  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6242  * \param pos output of size at least 3 used to store a point owned of searched plane.
6243  */
6244 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6245 {
6246   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6247     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6248   const int *conn=_nodal_connec->getConstPointer();
6249   const int *connI=_nodal_connec_index->getConstPointer();
6250   const double *coordsPtr=_coords->getConstPointer();
6251   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6252   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6253 }
6254
6255 /*!
6256  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6257  * cells. Currently cells of the following types are treated:
6258  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6259  * For a cell of other type an exception is thrown.
6260  * Space dimension of a 2D mesh can be either 2 or 3.
6261  * The Edge Ratio of a cell \f$t\f$ is: 
6262  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
6263  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6264  *  the smallest edge lengths of \f$t\f$.
6265  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6266  *          cells and one time, lying on \a this mesh. The caller is to delete this
6267  *          field using decrRef() as it is no more needed. 
6268  *  \throw If the coordinates array is not set.
6269  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6270  *  \throw If the connectivity data array has more than one component.
6271  *  \throw If the connectivity data array has a named component.
6272  *  \throw If the connectivity index data array has more than one component.
6273  *  \throw If the connectivity index data array has a named component.
6274  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6275  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6276  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6277  */
6278 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6279 {
6280   checkCoherency();
6281   int spaceDim=getSpaceDimension();
6282   int meshDim=getMeshDimension();
6283   if(spaceDim!=2 && spaceDim!=3)
6284     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6285   if(meshDim!=2 && meshDim!=3)
6286     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6287   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6288   ret->setMesh(this);
6289   int nbOfCells=getNumberOfCells();
6290   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6291   arr->alloc(nbOfCells,1);
6292   double *pt=arr->getPointer();
6293   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6294   const int *conn=_nodal_connec->getConstPointer();
6295   const int *connI=_nodal_connec_index->getConstPointer();
6296   const double *coo=_coords->getConstPointer();
6297   double tmp[12];
6298   for(int i=0;i<nbOfCells;i++,pt++)
6299     {
6300       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6301       switch(t)
6302       {
6303         case INTERP_KERNEL::NORM_TRI3:
6304           {
6305             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6306             *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6307             break;
6308           }
6309         case INTERP_KERNEL::NORM_QUAD4:
6310           {
6311             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6312             *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6313             break;
6314           }
6315         case INTERP_KERNEL::NORM_TETRA4:
6316           {
6317             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6318             *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6319             break;
6320           }
6321         default:
6322           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6323       }
6324       conn+=connI[i+1]-connI[i];
6325     }
6326   ret->setName("EdgeRatio");
6327   ret->synchronizeTimeWithSupport();
6328   return ret.retn();
6329 }
6330
6331 /*!
6332  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6333  * cells. Currently cells of the following types are treated:
6334  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6335  * For a cell of other type an exception is thrown.
6336  * Space dimension of a 2D mesh can be either 2 or 3.
6337  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6338  *          cells and one time, lying on \a this mesh. The caller is to delete this
6339  *          field using decrRef() as it is no more needed. 
6340  *  \throw If the coordinates array is not set.
6341  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6342  *  \throw If the connectivity data array has more than one component.
6343  *  \throw If the connectivity data array has a named component.
6344  *  \throw If the connectivity index data array has more than one component.
6345  *  \throw If the connectivity index data array has a named component.
6346  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
6347  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6348  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6349  */
6350 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6351 {
6352   checkCoherency();
6353   int spaceDim=getSpaceDimension();
6354   int meshDim=getMeshDimension();
6355   if(spaceDim!=2 && spaceDim!=3)
6356     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6357   if(meshDim!=2 && meshDim!=3)
6358     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6359   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6360   ret->setMesh(this);
6361   int nbOfCells=getNumberOfCells();
6362   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6363   arr->alloc(nbOfCells,1);
6364   double *pt=arr->getPointer();
6365   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6366   const int *conn=_nodal_connec->getConstPointer();
6367   const int *connI=_nodal_connec_index->getConstPointer();
6368   const double *coo=_coords->getConstPointer();
6369   double tmp[12];
6370   for(int i=0;i<nbOfCells;i++,pt++)
6371     {
6372       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6373       switch(t)
6374       {
6375         case INTERP_KERNEL::NORM_TRI3:
6376           {
6377             FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6378             *pt=INTERP_KERNEL::triAspectRatio(tmp);
6379             break;
6380           }
6381         case INTERP_KERNEL::NORM_QUAD4:
6382           {
6383             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6384             *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6385             break;
6386           }
6387         case INTERP_KERNEL::NORM_TETRA4:
6388           {
6389             FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6390             *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6391             break;
6392           }
6393         default:
6394           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6395       }
6396       conn+=connI[i+1]-connI[i];
6397     }
6398   ret->setName("AspectRatio");
6399   ret->synchronizeTimeWithSupport();
6400   return ret.retn();
6401 }
6402
6403 /*!
6404  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6405  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6406  * treated: INTERP_KERNEL::NORM_QUAD4.
6407  * For a cell of other type an exception is thrown.
6408  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6409  *          cells and one time, lying on \a this mesh. The caller is to delete this
6410  *          field using decrRef() as it is no more needed. 
6411  *  \throw If the coordinates array is not set.
6412  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6413  *  \throw If the connectivity data array has more than one component.
6414  *  \throw If the connectivity data array has a named component.
6415  *  \throw If the connectivity index data array has more than one component.
6416  *  \throw If the connectivity index data array has a named component.
6417  *  \throw If \a this->getMeshDimension() != 2.
6418  *  \throw If \a this->getSpaceDimension() != 3.
6419  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6420  */
6421 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6422 {
6423   checkCoherency();
6424   int spaceDim=getSpaceDimension();
6425   int meshDim=getMeshDimension();
6426   if(spaceDim!=3)
6427     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6428   if(meshDim!=2)
6429     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6430   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6431   ret->setMesh(this);
6432   int nbOfCells=getNumberOfCells();
6433   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6434   arr->alloc(nbOfCells,1);
6435   double *pt=arr->getPointer();
6436   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6437   const int *conn=_nodal_connec->getConstPointer();
6438   const int *connI=_nodal_connec_index->getConstPointer();
6439   const double *coo=_coords->getConstPointer();
6440   double tmp[12];
6441   for(int i=0;i<nbOfCells;i++,pt++)
6442     {
6443       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6444       switch(t)
6445       {
6446         case INTERP_KERNEL::NORM_QUAD4:
6447           {
6448             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6449             *pt=INTERP_KERNEL::quadWarp(tmp);
6450             break;
6451           }
6452         default:
6453           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6454       }
6455       conn+=connI[i+1]-connI[i];
6456     }
6457   ret->setName("Warp");
6458   ret->synchronizeTimeWithSupport();
6459   return ret.retn();
6460 }
6461
6462
6463 /*!
6464  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6465  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6466  * treated: INTERP_KERNEL::NORM_QUAD4.
6467  * For a cell of other type an exception is thrown.
6468  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6469  *          cells and one time, lying on \a this mesh. The caller is to delete this
6470  *          field using decrRef() as it is no more needed. 
6471  *  \throw If the coordinates array is not set.
6472  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6473  *  \throw If the connectivity data array has more than one component.
6474  *  \throw If the connectivity data array has a named component.
6475  *  \throw If the connectivity index data array has more than one component.
6476  *  \throw If the connectivity index data array has a named component.
6477  *  \throw If \a this->getMeshDimension() != 2.
6478  *  \throw If \a this->getSpaceDimension() != 3.
6479  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6480  */
6481 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6482 {
6483   checkCoherency();
6484   int spaceDim=getSpaceDimension();
6485   int meshDim=getMeshDimension();
6486   if(spaceDim!=3)
6487     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6488   if(meshDim!=2)
6489     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6490   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6491   ret->setMesh(this);
6492   int nbOfCells=getNumberOfCells();
6493   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6494   arr->alloc(nbOfCells,1);
6495   double *pt=arr->getPointer();
6496   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6497   const int *conn=_nodal_connec->getConstPointer();
6498   const int *connI=_nodal_connec_index->getConstPointer();
6499   const double *coo=_coords->getConstPointer();
6500   double tmp[12];
6501   for(int i=0;i<nbOfCells;i++,pt++)
6502     {
6503       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6504       switch(t)
6505       {
6506         case INTERP_KERNEL::NORM_QUAD4:
6507           {
6508             FillInCompact3DMode(3,4,conn+1,coo,tmp);
6509             *pt=INTERP_KERNEL::quadSkew(tmp);
6510             break;
6511           }
6512         default:
6513           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6514       }
6515       conn+=connI[i+1]-connI[i];
6516     }
6517   ret->setName("Skew");
6518   ret->synchronizeTimeWithSupport();
6519   return ret.retn();
6520 }
6521
6522 /*!
6523  * 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.
6524  *
6525  * \return a new instance of field containing the result. The returned instance has to be deallocated by the caller.
6526  *
6527  * \sa getSkewField, getWarpField, getAspectRatioField, getEdgeRatioField
6528  */
6529 MEDCouplingFieldDouble *MEDCouplingUMesh::computeDiameterField() const
6530 {
6531   checkCoherency();
6532   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
6533   ret->setMesh(this);
6534   std::set<INTERP_KERNEL::NormalizedCellType> types;
6535   ComputeAllTypesInternal(types,_nodal_connec,_nodal_connec_index);
6536   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells());
6537   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New());
6538   arr->alloc(nbCells,1);
6539   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++)
6540     {
6541       INTERP_KERNEL::AutoCppPtr<INTERP_KERNEL::DiameterCalculator> dc(INTERP_KERNEL::CellModel::GetCellModel(*it).buildInstanceOfDiameterCalulator(spaceDim));
6542       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds(giveCellsWithType(*it));
6543       dc->computeForListOfCellIdsUMeshFrmt(cellIds->begin(),cellIds->end(),_nodal_connec_index->begin(),_nodal_connec->begin(),getCoords()->begin(),arr->getPointer());
6544     }
6545   ret->setArray(arr);
6546   ret->setName("Diameter");
6547   return ret.retn();
6548 }
6549
6550 /*!
6551  * This method aggregate the bbox of each cell and put it into bbox parameter.
6552  * 
6553  * \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)
6554  *                         For all other cases this input parameter is ignored.
6555  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6556  * 
6557  * \throw If \a this is not fully set (coordinates and connectivity).
6558  * \throw If a cell in \a this has no valid nodeId.
6559  * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6560  */
6561 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6562 {
6563   int mDim(getMeshDimension()),sDim(getSpaceDimension());
6564   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.
6565     return getBoundingBoxForBBTreeFast();
6566   if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6567     {
6568       bool presenceOfQuadratic(false);
6569       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6570         {
6571           const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6572           if(cm.isQuadratic())
6573             presenceOfQuadratic=true;
6574         }
6575       if(!presenceOfQuadratic)
6576         return getBoundingBoxForBBTreeFast();
6577       if(mDim==2 && sDim==2)
6578         return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6579       else
6580         return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6581     }
6582   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) !");
6583 }
6584
6585 /*!
6586  * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6587  * So meshes having quadratic cells the computed bounding boxes can be invalid !
6588  * 
6589  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6590  * 
6591  * \throw If \a this is not fully set (coordinates and connectivity).
6592  * \throw If a cell in \a this has no valid nodeId.
6593  */
6594 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6595 {
6596   checkFullyDefined();
6597   int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6598   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6599   double *bbox(ret->getPointer());
6600   for(int i=0;i<nbOfCells*spaceDim;i++)
6601     {
6602       bbox[2*i]=std::numeric_limits<double>::max();
6603       bbox[2*i+1]=-std::numeric_limits<double>::max();
6604     }
6605   const double *coordsPtr(_coords->getConstPointer());
6606   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6607   for(int i=0;i<nbOfCells;i++)
6608     {
6609       int offset=connI[i]+1;
6610       int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6611       for(int j=0;j<nbOfNodesForCell;j++)
6612         {
6613           int nodeId=conn[offset+j];
6614           if(nodeId>=0 && nodeId<nbOfNodes)
6615             {
6616               for(int k=0;k<spaceDim;k++)
6617                 {
6618                   bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6619                   bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6620                 }
6621               kk++;
6622             }
6623         }
6624       if(kk==0)
6625         {
6626           std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6627           throw INTERP_KERNEL::Exception(oss.str().c_str());
6628         }
6629     }
6630   return ret.retn();
6631 }
6632
6633 /*!
6634  * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6635  * useful for 2D meshes having quadratic cells
6636  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6637  * the two extremities of the arc of circle).
6638  * 
6639  * \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)
6640  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6641  * \throw If \a this is not fully defined.
6642  * \throw If \a this is not a mesh with meshDimension equal to 2.
6643  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6644  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6645  */
6646 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6647 {
6648   checkFullyDefined();
6649   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6650   if(spaceDim!=2 || mDim!=2)
6651     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!");
6652   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6653   double *bbox(ret->getPointer());
6654   const double *coords(_coords->getConstPointer());
6655   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6656   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6657     {
6658       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6659       int sz(connI[1]-connI[0]-1);
6660       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6661       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6662       INTERP_KERNEL::QuadraticPolygon *pol(0);
6663       for(int j=0;j<sz;j++)
6664         {
6665           int nodeId(conn[*connI+1+j]);
6666           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6667         }
6668       if(!cm.isQuadratic())
6669         pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6670       else
6671         pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6672       INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6673       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); 
6674     }
6675   return ret.retn();
6676 }
6677
6678 /*!
6679  * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6680  * useful for 2D meshes having quadratic cells
6681  * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6682  * the two extremities of the arc of circle).
6683  * 
6684  * \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)
6685  * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6686  * \throw If \a this is not fully defined.
6687  * \throw If \a this is not a mesh with meshDimension equal to 1.
6688  * \throw If \a this is not a mesh with spaceDimension equal to 2.
6689  * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6690  */
6691 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6692 {
6693   checkFullyDefined();
6694   int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6695   if(spaceDim!=2 || mDim!=1)
6696     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!");
6697   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6698   double *bbox(ret->getPointer());
6699   const double *coords(_coords->getConstPointer());
6700   const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6701   for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6702     {
6703       const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6704       int sz(connI[1]-connI[0]-1);
6705       INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6706       std::vector<INTERP_KERNEL::Node *> nodes(sz);
6707       INTERP_KERNEL::Edge *edge(0);
6708       for(int j=0;j<sz;j++)
6709         {
6710           int nodeId(conn[*connI+1+j]);
6711           nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6712         }
6713       if(!cm.isQuadratic())
6714         edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6715       else
6716         edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6717       const INTERP_KERNEL::Bounds& b(edge->getBounds());
6718       bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6719     }
6720   return ret.retn();
6721 }
6722
6723 /// @cond INTERNAL
6724
6725 namespace ParaMEDMEMImpl
6726 {
6727   class ConnReader
6728   {
6729   public:
6730     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6731     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6732   private:
6733     const int *_conn;
6734     int _val;
6735   };
6736
6737   class ConnReader2
6738   {
6739   public:
6740     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6741     bool operator() (const int& pos) { return _conn[pos]==_val; }
6742   private:
6743     const int *_conn;
6744     int _val;
6745   };
6746 }
6747
6748 /// @endcond
6749
6750 /*!
6751  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6752  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6753  * \a this is composed in cell types.
6754  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6755  * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here. 
6756  * This parameter is kept only for compatibility with other methode listed above.
6757  */
6758 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6759 {
6760   checkConnectivityFullyDefined();
6761   const int *conn=_nodal_connec->getConstPointer();
6762   const int *connI=_nodal_connec_index->getConstPointer();
6763   const int *work=connI;
6764   int nbOfCells=getNumberOfCells();
6765   std::size_t n=getAllGeoTypes().size();
6766   std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6767   std::set<INTERP_KERNEL::NormalizedCellType> types;
6768   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6769     {
6770       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6771       if(types.find(typ)!=types.end())
6772         {
6773           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6774           oss << " is not contiguous !";
6775           throw INTERP_KERNEL::Exception(oss.str().c_str());
6776         }
6777       types.insert(typ);
6778       ret[3*i]=typ;
6779       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6780       ret[3*i+1]=(int)std::distance(work,work2);
6781       work=work2;
6782     }
6783   return ret;
6784 }
6785
6786 /*!
6787  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6788  * only for types cell, type node is not managed.
6789  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6790  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6791  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6792  * If 2 or more same geometric type is in \a code and exception is thrown too.
6793  *
6794  * This method firstly checks
6795  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6796  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6797  * an exception is thrown too.
6798  * 
6799  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6800  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6801  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6802  */
6803 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6804 {
6805   if(code.empty())
6806     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6807   std::size_t sz=code.size();
6808   std::size_t n=sz/3;
6809   if(sz%3!=0)
6810     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6811   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6812   int nb=0;
6813   bool isNoPflUsed=true;
6814   for(std::size_t i=0;i<n;i++)
6815     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6816       {
6817         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6818         nb+=code[3*i+1];
6819         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6820           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6821         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6822       }
6823   if(types.size()!=n)
6824     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6825   if(isNoPflUsed)
6826     {
6827       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6828         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6829       if(types.size()==_types.size())
6830         return 0;
6831     }
6832   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6833   ret->alloc(nb,1);
6834   int *retPtr=ret->getPointer();
6835   const int *connI=_nodal_connec_index->getConstPointer();
6836   const int *conn=_nodal_connec->getConstPointer();
6837   int nbOfCells=getNumberOfCells();
6838   const int *i=connI;
6839   int kk=0;
6840   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6841     {
6842       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6843       int offset=(int)std::distance(connI,i);
6844       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6845       int nbOfCellsOfCurType=(int)std::distance(i,j);
6846       if(code[3*kk+2]==-1)
6847         for(int k=0;k<nbOfCellsOfCurType;k++)
6848           *retPtr++=k+offset;
6849       else
6850         {
6851           int idInIdsPerType=code[3*kk+2];
6852           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6853             {
6854               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6855               if(zePfl)
6856                 {
6857                   zePfl->checkAllocated();
6858                   if(zePfl->getNumberOfComponents()==1)
6859                     {
6860                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6861                         {
6862                           if(*k>=0 && *k<nbOfCellsOfCurType)
6863                             *retPtr=(*k)+offset;
6864                           else
6865                             {
6866                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6867                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6868                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6869                             }
6870                         }
6871                     }
6872                   else
6873                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6874                 }
6875               else
6876                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6877             }
6878           else
6879             {
6880               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6881               oss << " should be in [0," << idsPerType.size() << ") !";
6882               throw INTERP_KERNEL::Exception(oss.str().c_str());
6883             }
6884         }
6885       i=j;
6886     }
6887   return ret.retn();
6888 }
6889
6890 /*!
6891  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6892  * 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.
6893  * 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.
6894  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6895  * 
6896  * \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.
6897  * \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,
6898  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6899  * \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.
6900  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6901  * \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
6902  */
6903 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6904 {
6905   if(!profile)
6906     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6907   if(profile->getNumberOfComponents()!=1)
6908     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6909   checkConnectivityFullyDefined();
6910   const int *conn=_nodal_connec->getConstPointer();
6911   const int *connI=_nodal_connec_index->getConstPointer();
6912   int nbOfCells=getNumberOfCells();
6913   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6914   std::vector<int> typeRangeVals(1);
6915   for(const int *i=connI;i!=connI+nbOfCells;)
6916     {
6917       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6918       if(std::find(types.begin(),types.end(),curType)!=types.end())
6919         {
6920           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6921         }
6922       types.push_back(curType);
6923       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6924       typeRangeVals.push_back((int)std::distance(connI,i));
6925     }
6926   //
6927   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6928   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6929   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6930   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6931   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6932   //
6933   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6934   code.resize(3*nbOfCastsFinal);
6935   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6936   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6937   for(int i=0;i<nbOfCastsFinal;i++)
6938     {
6939       int castId=castsPresent->getIJ(i,0);
6940       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6941       idsInPflPerType2.push_back(tmp3);
6942       code[3*i]=(int)types[castId];
6943       code[3*i+1]=tmp3->getNumberOfTuples();
6944       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6945       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6946         {
6947           tmp4->copyStringInfoFrom(*profile);
6948           idsPerType2.push_back(tmp4);
6949           code[3*i+2]=(int)idsPerType2.size()-1;
6950         }
6951       else
6952         {
6953           code[3*i+2]=-1;
6954         }
6955     }
6956   std::size_t sz2=idsInPflPerType2.size();
6957   idsInPflPerType.resize(sz2);
6958   for(std::size_t i=0;i<sz2;i++)
6959     {
6960       DataArrayInt *locDa=idsInPflPerType2[i];
6961       locDa->incrRef();
6962       idsInPflPerType[i]=locDa;
6963     }
6964   std::size_t sz=idsPerType2.size();
6965   idsPerType.resize(sz);
6966   for(std::size_t i=0;i<sz;i++)
6967     {
6968       DataArrayInt *locDa=idsPerType2[i];
6969       locDa->incrRef();
6970       idsPerType[i]=locDa;
6971     }
6972 }
6973
6974 /*!
6975  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6976  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6977  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6978  * 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.
6979  */
6980 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6981 {
6982   checkFullyDefined();
6983   nM1LevMesh->checkFullyDefined();
6984   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6985     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6986   if(_coords!=nM1LevMesh->getCoords())
6987     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6988   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6989   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6990   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6991   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6992   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6993   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6994   tmp->setConnectivity(tmp0,tmp1);
6995   tmp->renumberCells(ret0->getConstPointer(),false);
6996   revDesc=tmp->getNodalConnectivity();
6997   revDescIndx=tmp->getNodalConnectivityIndex();
6998   DataArrayInt *ret=0;
6999   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
7000     {
7001       int tmp2;
7002       ret->getMaxValue(tmp2);
7003       ret->decrRef();
7004       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
7005       throw INTERP_KERNEL::Exception(oss.str().c_str());
7006     }
7007   nM1LevMeshIds=ret;
7008   //
7009   revDesc->incrRef();
7010   revDescIndx->incrRef();
7011   ret1->incrRef();
7012   ret0->incrRef();
7013   meshnM1Old2New=ret0;
7014   return ret1;
7015 }
7016
7017 /*!
7018  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
7019  * necessary for writing the mesh to MED file. Additionally returns a permutation array
7020  * in "Old to New" mode.
7021  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
7022  *          this array using decrRef() as it is no more needed.
7023  *  \throw If the nodal connectivity of cells is not defined.
7024  */
7025 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
7026 {
7027   checkConnectivityFullyDefined();
7028   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
7029   renumberCells(ret->getConstPointer(),false);
7030   return ret.retn();
7031 }
7032
7033 /*!
7034  * This methods checks that cells are sorted by their types.
7035  * This method makes asumption (no check) that connectivity is correctly set before calling.
7036  */
7037 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
7038 {
7039   checkFullyDefined();
7040   const int *conn=_nodal_connec->getConstPointer();
7041   const int *connI=_nodal_connec_index->getConstPointer();
7042   int nbOfCells=getNumberOfCells();
7043   std::set<INTERP_KERNEL::NormalizedCellType> types;
7044   for(const int *i=connI;i!=connI+nbOfCells;)
7045     {
7046       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7047       if(types.find(curType)!=types.end())
7048         return false;
7049       types.insert(curType);
7050       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7051     }
7052   return true;
7053 }
7054
7055 /*!
7056  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
7057  * The geometric type order is specified by MED file.
7058  * 
7059  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
7060  */
7061 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
7062 {
7063   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7064 }
7065
7066 /*!
7067  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
7068  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
7069  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
7070  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
7071  */
7072 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7073 {
7074   checkFullyDefined();
7075   const int *conn=_nodal_connec->getConstPointer();
7076   const int *connI=_nodal_connec_index->getConstPointer();
7077   int nbOfCells=getNumberOfCells();
7078   if(nbOfCells==0)
7079     return true;
7080   int lastPos=-1;
7081   std::set<INTERP_KERNEL::NormalizedCellType> sg;
7082   for(const int *i=connI;i!=connI+nbOfCells;)
7083     {
7084       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7085       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
7086       if(isTypeExists!=orderEnd)
7087         {
7088           int pos=(int)std::distance(orderBg,isTypeExists);
7089           if(pos<=lastPos)
7090             return false;
7091           lastPos=pos;
7092           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7093         }
7094       else
7095         {
7096           if(sg.find(curType)==sg.end())
7097             {
7098               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7099               sg.insert(curType);
7100             }
7101           else
7102             return false;
7103         }
7104     }
7105   return true;
7106 }
7107
7108 /*!
7109  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
7110  * 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
7111  * 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'.
7112  */
7113 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
7114 {
7115   checkConnectivityFullyDefined();
7116   int nbOfCells=getNumberOfCells();
7117   const int *conn=_nodal_connec->getConstPointer();
7118   const int *connI=_nodal_connec_index->getConstPointer();
7119   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
7120   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
7121   tmpa->alloc(nbOfCells,1);
7122   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
7123   tmpb->fillWithZero();
7124   int *tmp=tmpa->getPointer();
7125   int *tmp2=tmpb->getPointer();
7126   for(const int *i=connI;i!=connI+nbOfCells;i++)
7127     {
7128       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
7129       if(where!=orderEnd)
7130         {
7131           int pos=(int)std::distance(orderBg,where);
7132           tmp2[pos]++;
7133           tmp[std::distance(connI,i)]=pos;
7134         }
7135       else
7136         {
7137           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
7138           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
7139           oss << " has a type " << cm.getRepr() << " not in input array of type !";
7140           throw INTERP_KERNEL::Exception(oss.str().c_str());
7141         }
7142     }
7143   nbPerType=tmpb.retn();
7144   return tmpa.retn();
7145 }
7146
7147 /*!
7148  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
7149  *
7150  * \return a new object containing the old to new correspondance.
7151  *
7152  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7153  */
7154 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
7155 {
7156   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
7157 }
7158
7159 /*!
7160  * 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.
7161  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
7162  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
7163  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
7164  */
7165 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
7166 {
7167   DataArrayInt *nbPerType=0;
7168   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
7169   nbPerType->decrRef();
7170   return tmpa->buildPermArrPerLevel();
7171 }
7172
7173 /*!
7174  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
7175  * The number of cells remains unchanged after the call of this method.
7176  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
7177  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
7178  *
7179  * \return the array giving the correspondance old to new.
7180  */
7181 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
7182 {
7183   checkFullyDefined();
7184   computeTypes();
7185   const int *conn=_nodal_connec->getConstPointer();
7186   const int *connI=_nodal_connec_index->getConstPointer();
7187   int nbOfCells=getNumberOfCells();
7188   std::vector<INTERP_KERNEL::NormalizedCellType> types;
7189   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
7190     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
7191       {
7192         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7193         types.push_back(curType);
7194         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
7195       }
7196   DataArrayInt *ret=DataArrayInt::New();
7197   ret->alloc(nbOfCells,1);
7198   int *retPtr=ret->getPointer();
7199   std::fill(retPtr,retPtr+nbOfCells,-1);
7200   int newCellId=0;
7201   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7202     {
7203       for(const int *i=connI;i!=connI+nbOfCells;i++)
7204         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7205           retPtr[std::distance(connI,i)]=newCellId++;
7206     }
7207   renumberCells(retPtr,false);
7208   return ret;
7209 }
7210
7211 /*!
7212  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7213  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7214  * This method makes asumption that connectivity is correctly set before calling.
7215  */
7216 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7217 {
7218   checkConnectivityFullyDefined();
7219   const int *conn=_nodal_connec->getConstPointer();
7220   const int *connI=_nodal_connec_index->getConstPointer();
7221   int nbOfCells=getNumberOfCells();
7222   std::vector<MEDCouplingUMesh *> ret;
7223   for(const int *i=connI;i!=connI+nbOfCells;)
7224     {
7225       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7226       int beginCellId=(int)std::distance(connI,i);
7227       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7228       int endCellId=(int)std::distance(connI,i);
7229       int sz=endCellId-beginCellId;
7230       int *cells=new int[sz];
7231       for(int j=0;j<sz;j++)
7232         cells[j]=beginCellId+j;
7233       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7234       delete [] cells;
7235       ret.push_back(m);
7236     }
7237   return ret;
7238 }
7239
7240 /*!
7241  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7242  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7243  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7244  *
7245  * \return a newly allocated instance, that the caller must manage.
7246  * \throw If \a this contains more than one geometric type.
7247  * \throw If the nodal connectivity of \a this is not fully defined.
7248  * \throw If the internal data is not coherent.
7249  */
7250 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7251 {
7252   checkConnectivityFullyDefined();
7253   if(_types.size()!=1)
7254     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7255   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7256   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7257   ret->setCoords(getCoords());
7258   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7259   if(retC)
7260     {
7261       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7262       retC->setNodalConnectivity(c);
7263     }
7264   else
7265     {
7266       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7267       if(!retD)
7268         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7269       DataArrayInt *c=0,*ci=0;
7270       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7271       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7272       retD->setNodalConnectivity(cs,cis);
7273     }
7274   return ret.retn();
7275 }
7276
7277 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7278 {
7279   checkConnectivityFullyDefined();
7280   if(_types.size()!=1)
7281     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7282   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7283   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7284   if(cm.isDynamic())
7285     {
7286       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7287       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7288       throw INTERP_KERNEL::Exception(oss.str().c_str());
7289     }
7290   int nbCells=getNumberOfCells();
7291   int typi=(int)typ;
7292   int nbNodesPerCell=(int)cm.getNumberOfNodes();
7293   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7294   int *outPtr=connOut->getPointer();
7295   const int *conn=_nodal_connec->begin();
7296   const int *connI=_nodal_connec_index->begin();
7297   nbNodesPerCell++;
7298   for(int i=0;i<nbCells;i++,connI++)
7299     {
7300       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7301         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7302       else
7303         {
7304           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 << ") !";
7305           throw INTERP_KERNEL::Exception(oss.str().c_str());
7306         }
7307     }
7308   return connOut.retn();
7309 }
7310
7311 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7312 {
7313   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7314   checkConnectivityFullyDefined();
7315   if(_types.size()!=1)
7316     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7317   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7318   if(lgth<nbCells)
7319     throw INTERP_KERNEL::Exception(msg0);
7320   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7321   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7322   int *cp(c->getPointer()),*cip(ci->getPointer());
7323   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7324   cip[0]=0;
7325   for(int i=0;i<nbCells;i++,cip++,incip++)
7326     {
7327       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7328       int delta(stop-strt);
7329       if(delta>=1)
7330         {
7331           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7332             cp=std::copy(incp+strt,incp+stop,cp);
7333           else
7334             throw INTERP_KERNEL::Exception(msg0);
7335         }
7336       else
7337         throw INTERP_KERNEL::Exception(msg0);
7338       cip[1]=cip[0]+delta;
7339     }
7340   nodalConn=c.retn(); nodalConnIndex=ci.retn();
7341 }
7342
7343 /*!
7344  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7345  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7346  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7347  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7348  * are not used here to avoid the build of big permutation array.
7349  *
7350  * \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
7351  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7352  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7353  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7354  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7355  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
7356  * \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
7357  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7358  */
7359 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7360                                                                             DataArrayInt *&szOfCellGrpOfSameType,
7361                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType)
7362 {
7363   std::vector<const MEDCouplingUMesh *> ms2;
7364   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7365     if(*it)
7366       {
7367         (*it)->checkConnectivityFullyDefined();
7368         ms2.push_back(*it);
7369       }
7370   if(ms2.empty())
7371     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7372   const DataArrayDouble *refCoo=ms2[0]->getCoords();
7373   int meshDim=ms2[0]->getMeshDimension();
7374   std::vector<const MEDCouplingUMesh *> m1ssm;
7375   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7376   //
7377   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7378   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7379   int fake=0,rk=0;
7380   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7381   ret1->alloc(0,1); ret2->alloc(0,1);
7382   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7383     {
7384       if(meshDim!=(*it)->getMeshDimension())
7385         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7386       if(refCoo!=(*it)->getCoords())
7387         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7388       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7389       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7390       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7391       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7392         {
7393           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7394           m1ssmSingleAuto.push_back(singleCell);
7395           m1ssmSingle.push_back(singleCell);
7396           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7397         }
7398     }
7399   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7400   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7401   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7402   for(std::size_t i=0;i<m1ssm.size();i++)
7403     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7404   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7405   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7406   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7407   return ret0.retn();
7408 }
7409
7410 /*!
7411  * This method returns a newly created DataArrayInt instance.
7412  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7413  */
7414 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7415 {
7416   checkFullyDefined();
7417   const int *conn=_nodal_connec->getConstPointer();
7418   const int *connIndex=_nodal_connec_index->getConstPointer();
7419   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7420   for(const int *w=begin;w!=end;w++)
7421     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7422       ret->pushBackSilent(*w);
7423   return ret.retn();
7424 }
7425
7426 /*!
7427  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7428  * are in [0:getNumberOfCells())
7429  */
7430 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7431 {
7432   checkFullyDefined();
7433   const int *conn=_nodal_connec->getConstPointer();
7434   const int *connI=_nodal_connec_index->getConstPointer();
7435   int nbOfCells=getNumberOfCells();
7436   std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7437   int *tmp=new int[nbOfCells];
7438   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7439     {
7440       int j=0;
7441       for(const int *i=connI;i!=connI+nbOfCells;i++)
7442         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7443           tmp[std::distance(connI,i)]=j++;
7444     }
7445   DataArrayInt *ret=DataArrayInt::New();
7446   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7447   ret->copyStringInfoFrom(*da);
7448   int *retPtr=ret->getPointer();
7449   const int *daPtr=da->getConstPointer();
7450   int nbOfElems=da->getNbOfElems();
7451   for(int k=0;k<nbOfElems;k++)
7452     retPtr[k]=tmp[daPtr[k]];
7453   delete [] tmp;
7454   return ret;
7455 }
7456
7457 /*!
7458  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7459  * This method \b works \b for mesh sorted by type.
7460  * cells whose ids is in 'idsPerGeoType' array.
7461  * This method conserves coords and name of mesh.
7462  */
7463 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7464 {
7465   std::vector<int> code=getDistributionOfTypes();
7466   std::size_t nOfTypesInThis=code.size()/3;
7467   int sz=0,szOfType=0;
7468   for(std::size_t i=0;i<nOfTypesInThis;i++)
7469     {
7470       if(code[3*i]!=type)
7471         sz+=code[3*i+1];
7472       else
7473         szOfType=code[3*i+1];
7474     }
7475   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7476     if(*work<0 || *work>=szOfType)
7477       {
7478         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7479         oss << ". It should be in [0," << szOfType << ") !";
7480         throw INTERP_KERNEL::Exception(oss.str().c_str());
7481       }
7482   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7483   int *idsPtr=idsTokeep->getPointer();
7484   int offset=0;
7485   for(std::size_t i=0;i<nOfTypesInThis;i++)
7486     {
7487       if(code[3*i]!=type)
7488         for(int j=0;j<code[3*i+1];j++)
7489           *idsPtr++=offset+j;
7490       else
7491         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7492       offset+=code[3*i+1];
7493     }
7494   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7495   ret->copyTinyInfoFrom(this);
7496   return ret.retn();
7497 }
7498
7499 /*!
7500  * This method returns a vector of size 'this->getNumberOfCells()'.
7501  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7502  */
7503 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7504 {
7505   int ncell=getNumberOfCells();
7506   std::vector<bool> ret(ncell);
7507   const int *cI=getNodalConnectivityIndex()->getConstPointer();
7508   const int *c=getNodalConnectivity()->getConstPointer();
7509   for(int i=0;i<ncell;i++)
7510     {
7511       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7512       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7513       ret[i]=cm.isQuadratic();
7514     }
7515   return ret;
7516 }
7517
7518 /*!
7519  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7520  */
7521 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7522 {
7523   if(other->getType()!=UNSTRUCTURED)
7524     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7525   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7526   return MergeUMeshes(this,otherC);
7527 }
7528
7529 /*!
7530  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7531  * computed by averaging coordinates of cell nodes, so this method is not a right
7532  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7533  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7534  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7535  *          components. The caller is to delete this array using decrRef() as it is
7536  *          no more needed.
7537  *  \throw If the coordinates array is not set.
7538  *  \throw If the nodal connectivity of cells is not defined.
7539  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7540  */
7541 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7542 {
7543   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7544   int spaceDim=getSpaceDimension();
7545   int nbOfCells=getNumberOfCells();
7546   ret->alloc(nbOfCells,spaceDim);
7547   ret->copyStringInfoFrom(*getCoords());
7548   double *ptToFill=ret->getPointer();
7549   const int *nodal=_nodal_connec->getConstPointer();
7550   const int *nodalI=_nodal_connec_index->getConstPointer();
7551   const double *coor=_coords->getConstPointer();
7552   for(int i=0;i<nbOfCells;i++)
7553     {
7554       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7555       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7556       ptToFill+=spaceDim;
7557     }
7558   return ret.retn();
7559 }
7560
7561 /*!
7562  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7563  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7564  * 
7565  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7566  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7567  * 
7568  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7569  * \throw If \a this is not fully defined (coordinates and connectivity)
7570  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7571  */
7572 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7573 {
7574   checkFullyDefined();
7575   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7576   int spaceDim=getSpaceDimension();
7577   int nbOfCells=getNumberOfCells();
7578   int nbOfNodes=getNumberOfNodes();
7579   ret->alloc(nbOfCells,spaceDim);
7580   double *ptToFill=ret->getPointer();
7581   const int *nodal=_nodal_connec->getConstPointer();
7582   const int *nodalI=_nodal_connec_index->getConstPointer();
7583   const double *coor=_coords->getConstPointer();
7584   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7585     {
7586       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7587       std::fill(ptToFill,ptToFill+spaceDim,0.);
7588       if(type!=INTERP_KERNEL::NORM_POLYHED)
7589         {
7590           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7591             {
7592               if(*conn>=0 && *conn<nbOfNodes)
7593                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7594               else
7595                 {
7596                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7597                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7598                 }
7599             }
7600           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7601           if(nbOfNodesInCell>0)
7602             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7603           else
7604             {
7605               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7606               throw INTERP_KERNEL::Exception(oss.str().c_str());
7607             }
7608         }
7609       else
7610         {
7611           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7612           s.erase(-1);
7613           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7614             {
7615               if(*it>=0 && *it<nbOfNodes)
7616                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7617               else
7618                 {
7619                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7620                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7621                 }
7622             }
7623           if(!s.empty())
7624             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7625           else
7626             {
7627               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7628               throw INTERP_KERNEL::Exception(oss.str().c_str());
7629             }
7630         }
7631     }
7632   return ret.retn();
7633 }
7634
7635 /*!
7636  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7637  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7638  * are specified via an array of cell ids. 
7639  *  \warning Validity of the specified cell ids is not checked! 
7640  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7641  *  \param [in] begin - an array of cell ids of interest.
7642  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7643  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7644  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7645  *          caller is to delete this array using decrRef() as it is no more needed. 
7646  *  \throw If the coordinates array is not set.
7647  *  \throw If the nodal connectivity of cells is not defined.
7648  *
7649  *  \if ENABLE_EXAMPLES
7650  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7651  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7652  *  \endif
7653  */
7654 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7655 {
7656   DataArrayDouble *ret=DataArrayDouble::New();
7657   int spaceDim=getSpaceDimension();
7658   int nbOfTuple=(int)std::distance(begin,end);
7659   ret->alloc(nbOfTuple,spaceDim);
7660   double *ptToFill=ret->getPointer();
7661   double *tmp=new double[spaceDim];
7662   const int *nodal=_nodal_connec->getConstPointer();
7663   const int *nodalI=_nodal_connec_index->getConstPointer();
7664   const double *coor=_coords->getConstPointer();
7665   for(const int *w=begin;w!=end;w++)
7666     {
7667       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7668       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7669       ptToFill+=spaceDim;
7670     }
7671   delete [] tmp;
7672   return ret;
7673 }
7674
7675 /*!
7676  * 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".
7677  * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7678  * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7679  * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7680  * This method is useful to detect 2D cells in 3D space that are not coplanar.
7681  * 
7682  * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7683  * \throw If spaceDim!=3 or meshDim!=2.
7684  * \throw If connectivity of \a this is invalid.
7685  * \throw If connectivity of a cell in \a this points to an invalid node.
7686  */
7687 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7688 {
7689   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7690   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7691   if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7692     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7693   ret->alloc(nbOfCells,4);
7694   double *retPtr(ret->getPointer());
7695   const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7696   const double *coor(_coords->begin());
7697   for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7698     {
7699       double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7700       if(nodalI[1]-nodalI[0]>=3)
7701         {
7702           for(int j=0;j<3;j++)
7703             {
7704               int nodeId(nodal[nodalI[0]+1+j]);
7705               if(nodeId>=0 && nodeId<nbOfNodes)
7706                 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7707               else
7708                 {
7709                   std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7710                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7711                 }
7712             }
7713         }
7714       else
7715         {
7716           std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7717           throw INTERP_KERNEL::Exception(oss.str().c_str());
7718         }
7719       INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7720       retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7721     }
7722   return ret.retn();
7723 }
7724
7725 /*!
7726  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7727  * 
7728  */
7729 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7730 {
7731   if(!da)
7732     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7733   da->checkAllocated();
7734   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7735   ret->setCoords(da);
7736   int nbOfTuples=da->getNumberOfTuples();
7737   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7738   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7739   c->alloc(2*nbOfTuples,1);
7740   cI->alloc(nbOfTuples+1,1);
7741   int *cp=c->getPointer();
7742   int *cip=cI->getPointer();
7743   *cip++=0;
7744   for(int i=0;i<nbOfTuples;i++)
7745     {
7746       *cp++=INTERP_KERNEL::NORM_POINT1;
7747       *cp++=i;
7748       *cip++=2*(i+1);
7749     }
7750   ret->setConnectivity(c,cI,true);
7751   return ret.retn();
7752 }
7753 /*!
7754  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7755  * Cells and nodes of
7756  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7757  *  \param [in] mesh1 - the first mesh.
7758  *  \param [in] mesh2 - the second mesh.
7759  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7760  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7761  *          is no more needed.
7762  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7763  *  \throw If the coordinates array is not set in none of the meshes.
7764  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7765  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7766  */
7767 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7768 {
7769   std::vector<const MEDCouplingUMesh *> tmp(2);
7770   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7771   return MergeUMeshes(tmp);
7772 }
7773
7774 /*!
7775  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7776  * Cells and nodes of
7777  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7778  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7779  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7780  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7781  *          is no more needed.
7782  *  \throw If \a a.size() == 0.
7783  *  \throw If \a a[ *i* ] == NULL.
7784  *  \throw If the coordinates array is not set in none of the meshes.
7785  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7786  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7787  */
7788 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7789 {
7790   std::size_t sz=a.size();
7791   if(sz==0)
7792     return MergeUMeshesLL(a);
7793   for(std::size_t ii=0;ii<sz;ii++)
7794     if(!a[ii])
7795       {
7796         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7797         throw INTERP_KERNEL::Exception(oss.str().c_str());
7798       }
7799   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7800   std::vector< const MEDCouplingUMesh * > aa(sz);
7801   int spaceDim=-3;
7802   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7803     {
7804       const MEDCouplingUMesh *cur=a[i];
7805       const DataArrayDouble *coo=cur->getCoords();
7806       if(coo)
7807         spaceDim=coo->getNumberOfComponents();
7808     }
7809   if(spaceDim==-3)
7810     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7811   for(std::size_t i=0;i<sz;i++)
7812     {
7813       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7814       aa[i]=bb[i];
7815     }
7816   return MergeUMeshesLL(aa);
7817 }
7818
7819 /// @cond INTERNAL
7820
7821 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7822 {
7823   if(a.empty())
7824     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7825   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7826   int meshDim=(*it)->getMeshDimension();
7827   int nbOfCells=(*it)->getNumberOfCells();
7828   int meshLgth=(*it++)->getMeshLength();
7829   for(;it!=a.end();it++)
7830     {
7831       if(meshDim!=(*it)->getMeshDimension())
7832         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7833       nbOfCells+=(*it)->getNumberOfCells();
7834       meshLgth+=(*it)->getMeshLength();
7835     }
7836   std::vector<const MEDCouplingPointSet *> aps(a.size());
7837   std::copy(a.begin(),a.end(),aps.begin());
7838   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7839   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7840   ret->setCoords(pts);
7841   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7842   c->alloc(meshLgth,1);
7843   int *cPtr=c->getPointer();
7844   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7845   cI->alloc(nbOfCells+1,1);
7846   int *cIPtr=cI->getPointer();
7847   *cIPtr++=0;
7848   int offset=0;
7849   int offset2=0;
7850   for(it=a.begin();it!=a.end();it++)
7851     {
7852       int curNbOfCell=(*it)->getNumberOfCells();
7853       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7854       const int *curC=(*it)->_nodal_connec->getConstPointer();
7855       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7856       for(int j=0;j<curNbOfCell;j++)
7857         {
7858           const int *src=curC+curCI[j];
7859           *cPtr++=*src++;
7860           for(;src!=curC+curCI[j+1];src++,cPtr++)
7861             {
7862               if(*src!=-1)
7863                 *cPtr=*src+offset2;
7864               else
7865                 *cPtr=-1;
7866             }
7867         }
7868       offset+=curCI[curNbOfCell];
7869       offset2+=(*it)->getNumberOfNodes();
7870     }
7871   //
7872   ret->setConnectivity(c,cI,true);
7873   return ret.retn();
7874 }
7875
7876 /// @endcond
7877
7878 /*!
7879  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7880  * dimension and sharing the node coordinates array.
7881  * All cells of the first mesh precede all cells of the second mesh
7882  * within the result mesh. 
7883  *  \param [in] mesh1 - the first mesh.
7884  *  \param [in] mesh2 - the second mesh.
7885  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7886  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7887  *          is no more needed.
7888  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7889  *  \throw If the meshes do not share the node coordinates array.
7890  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7891  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7892  */
7893 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7894 {
7895   std::vector<const MEDCouplingUMesh *> tmp(2);
7896   tmp[0]=mesh1; tmp[1]=mesh2;
7897   return MergeUMeshesOnSameCoords(tmp);
7898 }
7899
7900 /*!
7901  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7902  * dimension and sharing the node coordinates array.
7903  * All cells of the *i*-th mesh precede all cells of the
7904  * (*i*+1)-th mesh within the result mesh.
7905  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7906  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7907  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7908  *          is no more needed.
7909  *  \throw If \a a.size() == 0.
7910  *  \throw If \a a[ *i* ] == NULL.
7911  *  \throw If the meshes do not share the node coordinates array.
7912  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7913  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7914  */
7915 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7916 {
7917   if(meshes.empty())
7918     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7919   for(std::size_t ii=0;ii<meshes.size();ii++)
7920     if(!meshes[ii])
7921       {
7922         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7923         throw INTERP_KERNEL::Exception(oss.str().c_str());
7924       }
7925   const DataArrayDouble *coords=meshes.front()->getCoords();
7926   int meshDim=meshes.front()->getMeshDimension();
7927   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7928   int meshLgth=0;
7929   int meshIndexLgth=0;
7930   for(;iter!=meshes.end();iter++)
7931     {
7932       if(coords!=(*iter)->getCoords())
7933         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7934       if(meshDim!=(*iter)->getMeshDimension())
7935         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7936       meshLgth+=(*iter)->getMeshLength();
7937       meshIndexLgth+=(*iter)->getNumberOfCells();
7938     }
7939   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7940   nodal->alloc(meshLgth,1);
7941   int *nodalPtr=nodal->getPointer();
7942   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7943   nodalIndex->alloc(meshIndexLgth+1,1);
7944   int *nodalIndexPtr=nodalIndex->getPointer();
7945   int offset=0;
7946   for(iter=meshes.begin();iter!=meshes.end();iter++)
7947     {
7948       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7949       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7950       int nbOfCells=(*iter)->getNumberOfCells();
7951       int meshLgth2=(*iter)->getMeshLength();
7952       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7953       if(iter!=meshes.begin())
7954         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7955       else
7956         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7957       offset+=meshLgth2;
7958     }
7959   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7960   ret->setName("merge");
7961   ret->setMeshDimension(meshDim);
7962   ret->setConnectivity(nodal,nodalIndex,true);
7963   ret->setCoords(coords);
7964   return ret;
7965 }
7966
7967 /*!
7968  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7969  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7970  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7971  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7972  * New" mode are returned for each input mesh.
7973  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7974  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7975  *          valid values [0,1,2], see zipConnectivityTraducer().
7976  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7977  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7978  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7979  *          no more needed.
7980  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7981  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7982  *          is no more needed.
7983  *  \throw If \a meshes.size() == 0.
7984  *  \throw If \a meshes[ *i* ] == NULL.
7985  *  \throw If the meshes do not share the node coordinates array.
7986  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7987  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7988  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7989  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7990  */
7991 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7992 {
7993   //All checks are delegated to MergeUMeshesOnSameCoords
7994   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7995   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7996   corr.resize(meshes.size());
7997   std::size_t nbOfMeshes=meshes.size();
7998   int offset=0;
7999   const int *o2nPtr=o2n->getConstPointer();
8000   for(std::size_t i=0;i<nbOfMeshes;i++)
8001     {
8002       DataArrayInt *tmp=DataArrayInt::New();
8003       int curNbOfCells=meshes[i]->getNumberOfCells();
8004       tmp->alloc(curNbOfCells,1);
8005       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
8006       offset+=curNbOfCells;
8007       tmp->setName(meshes[i]->getName());
8008       corr[i]=tmp;
8009     }
8010   return ret.retn();
8011 }
8012
8013 /*!
8014  * Makes all given meshes share the nodal connectivity array. The common connectivity
8015  * array is created by concatenating the connectivity arrays of all given meshes. All
8016  * the given meshes must be of the same space dimension but dimension of cells **can
8017  * differ**. This method is particulary useful in MEDLoader context to build a \ref
8018  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8019  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
8020  *  \param [in,out] meshes - a vector of meshes to update.
8021  *  \throw If any of \a meshes is NULL.
8022  *  \throw If the coordinates array is not set in any of \a meshes.
8023  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8024  *  \throw If \a meshes are of different space dimension.
8025  */
8026 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
8027 {
8028   std::size_t sz=meshes.size();
8029   if(sz==0 || sz==1)
8030     return;
8031   std::vector< const DataArrayDouble * > coords(meshes.size());
8032   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
8033   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
8034     {
8035       if((*it))
8036         {
8037           (*it)->checkConnectivityFullyDefined();
8038           const DataArrayDouble *coo=(*it)->getCoords();
8039           if(coo)
8040             *it2=coo;
8041           else
8042             {
8043               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8044               oss << " has no coordinate array defined !";
8045               throw INTERP_KERNEL::Exception(oss.str().c_str());
8046             }
8047         }
8048       else
8049         {
8050           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
8051           oss << " is null !";
8052           throw INTERP_KERNEL::Exception(oss.str().c_str());
8053         }
8054     }
8055   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
8056   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
8057   int offset=(*it)->getNumberOfNodes();
8058   (*it++)->setCoords(res);
8059   for(;it!=meshes.end();it++)
8060     {
8061       int oldNumberOfNodes=(*it)->getNumberOfNodes();
8062       (*it)->setCoords(res);
8063       (*it)->shiftNodeNumbersInConn(offset);
8064       offset+=oldNumberOfNodes;
8065     }
8066 }
8067
8068 /*!
8069  * Merges nodes coincident with a given precision within all given meshes that share
8070  * the nodal connectivity array. The given meshes **can be of different** mesh
8071  * dimension. This method is particulary useful in MEDLoader context to build a \ref
8072  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
8073  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
8074  *  \param [in,out] meshes - a vector of meshes to update.
8075  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
8076  *  \throw If any of \a meshes is NULL.
8077  *  \throw If the \a meshes do not share the same node coordinates array.
8078  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
8079  */
8080 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
8081 {
8082   if(meshes.empty())
8083     return ;
8084   std::set<const DataArrayDouble *> s;
8085   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8086     {
8087       if(*it)
8088         s.insert((*it)->getCoords());
8089       else
8090         {
8091           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 !";
8092           throw INTERP_KERNEL::Exception(oss.str().c_str());
8093         }
8094     }
8095   if(s.size()!=1)
8096     {
8097       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 !";
8098       throw INTERP_KERNEL::Exception(oss.str().c_str());
8099     }
8100   const DataArrayDouble *coo=*(s.begin());
8101   if(!coo)
8102     return;
8103   //
8104   DataArrayInt *comm,*commI;
8105   coo->findCommonTuples(eps,-1,comm,commI);
8106   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
8107   int oldNbOfNodes=coo->getNumberOfTuples();
8108   int newNbOfNodes;
8109   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
8110   if(oldNbOfNodes==newNbOfNodes)
8111     return ;
8112   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
8113   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
8114     {
8115       (*it)->renumberNodesInConn(o2n->getConstPointer());
8116       (*it)->setCoords(newCoords);
8117     } 
8118 }
8119
8120 /*!
8121  * 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.
8122  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
8123  * \param isQuad specifies the policy of connectivity.
8124  * @ret in/out parameter in which the result will be append
8125  */
8126 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
8127 {
8128   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
8129   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
8130   ret.push_back(cm.getExtrudedType());
8131   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
8132   switch(flatType)
8133   {
8134     case INTERP_KERNEL::NORM_POINT1:
8135       {
8136         ret.push_back(connBg[1]);
8137         ret.push_back(connBg[1]+nbOfNodesPerLev);
8138         break;
8139       }
8140     case INTERP_KERNEL::NORM_SEG2:
8141       {
8142         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
8143         ret.insert(ret.end(),conn,conn+4);
8144         break;
8145       }
8146     case INTERP_KERNEL::NORM_SEG3:
8147       {
8148         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
8149         ret.insert(ret.end(),conn,conn+8);
8150         break;
8151       }
8152     case INTERP_KERNEL::NORM_QUAD4:
8153       {
8154         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
8155         ret.insert(ret.end(),conn,conn+8);
8156         break;
8157       }
8158     case INTERP_KERNEL::NORM_TRI3:
8159       {
8160         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
8161         ret.insert(ret.end(),conn,conn+6);
8162         break;
8163       }
8164     case INTERP_KERNEL::NORM_TRI6:
8165       {
8166         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,
8167           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
8168         ret.insert(ret.end(),conn,conn+15);
8169         break;
8170       }
8171     case INTERP_KERNEL::NORM_QUAD8:
8172       {
8173         int conn[20]={
8174           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
8175           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
8176           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
8177         };
8178         ret.insert(ret.end(),conn,conn+20);
8179         break;
8180       }
8181     case INTERP_KERNEL::NORM_POLYGON:
8182       {
8183         std::back_insert_iterator< std::vector<int> > ii(ret);
8184         std::copy(connBg+1,connEnd,ii);
8185         *ii++=-1;
8186         std::reverse_iterator<const int *> rConnBg(connEnd);
8187         std::reverse_iterator<const int *> rConnEnd(connBg+1);
8188         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
8189         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
8190         for(std::size_t i=0;i<nbOfRadFaces;i++)
8191           {
8192             *ii++=-1;
8193             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
8194             std::copy(conn,conn+4,ii);
8195           }
8196         break;
8197       }
8198     default:
8199       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8200   }
8201 }
8202
8203 /*!
8204  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8205  */
8206 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8207 {
8208   std::size_t i, ip1;
8209   double v[3]={0.,0.,0.};
8210   std::size_t sz=std::distance(begin,end);
8211   if(isQuadratic)
8212     sz/=2;
8213   for(i=0;i<sz;i++)
8214     {
8215       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];
8216       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8217       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8218     }
8219   double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8220
8221   // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8222   // SEG3 forming a circle):
8223   if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8224     {
8225       v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8226       for(std::size_t j=0;j<sz;j++)
8227         {
8228           if (j%2)  // current point i is quadratic, next point i+1 is standard
8229             {
8230               i = sz+j;
8231               ip1 = (j+1)%sz; // ip1 = "i+1"
8232             }
8233           else      // current point i is standard, next point i+1 is quadratic
8234             {
8235               i = j;
8236               ip1 = j+sz;
8237             }
8238           v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8239           v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8240           v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8241         }
8242       ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8243     }
8244   return (ret>0.);
8245 }
8246
8247 /*!
8248  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8249  */
8250 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8251 {
8252   std::vector<std::pair<int,int> > edges;
8253   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8254   const int *bgFace=begin;
8255   for(std::size_t i=0;i<nbOfFaces;i++)
8256     {
8257       const int *endFace=std::find(bgFace+1,end,-1);
8258       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8259       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8260         {
8261           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8262           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8263             return false;
8264           edges.push_back(p1);
8265         }
8266       bgFace=endFace+1;
8267     }
8268   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8269 }
8270
8271 /*!
8272  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8273  */
8274 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8275 {
8276   double vec0[3],vec1[3];
8277   std::size_t sz=std::distance(begin,end);
8278   if(sz%2!=0)
8279     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8280   int nbOfNodes=(int)sz/2;
8281   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8282   const double *pt0=coords+3*begin[0];
8283   const double *pt1=coords+3*begin[nbOfNodes];
8284   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8285   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8286 }
8287
8288 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8289 {
8290   std::size_t sz=std::distance(begin,end);
8291   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8292   std::size_t nbOfNodes(sz/2);
8293   std::copy(begin,end,(int *)tmp);
8294   for(std::size_t j=1;j<nbOfNodes;j++)
8295     {
8296       begin[j]=tmp[nbOfNodes-j];
8297       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8298     }
8299 }
8300
8301 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8302 {
8303   std::size_t sz=std::distance(begin,end);
8304   if(sz!=4)
8305     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8306   double vec0[3],vec1[3];
8307   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8308   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]; 
8309   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;
8310 }
8311
8312 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8313 {
8314   std::size_t sz=std::distance(begin,end);
8315   if(sz!=5)
8316     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8317   double vec0[3];
8318   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8319   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8320   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8321 }
8322
8323 /*!
8324  * 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 ) 
8325  * 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
8326  * a 2D space.
8327  *
8328  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8329  * \param [in] coords the coordinates with nb of components exactly equal to 3
8330  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8331  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8332  * \param [out] res the result is put at the end of the vector without any alteration of the data.
8333  */
8334 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8335 {
8336   int nbFaces=std::count(begin+1,end,-1)+1;
8337   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8338   double *vPtr=v->getPointer();
8339   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8340   double *pPtr=p->getPointer();
8341   const int *stFaceConn=begin+1;
8342   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8343     {
8344       const int *endFaceConn=std::find(stFaceConn,end,-1);
8345       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8346       stFaceConn=endFaceConn+1;
8347     }
8348   pPtr=p->getPointer(); vPtr=v->getPointer();
8349   DataArrayInt *comm1=0,*commI1=0;
8350   v->findCommonTuples(eps,-1,comm1,commI1);
8351   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8352   const int *comm1Ptr=comm1->getConstPointer();
8353   const int *commI1Ptr=commI1->getConstPointer();
8354   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8355   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8356   //
8357   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8358   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8359   mm->finishInsertingCells();
8360   //
8361   for(int i=0;i<nbOfGrps1;i++)
8362     {
8363       int vecId=comm1Ptr[commI1Ptr[i]];
8364       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8365       DataArrayInt *comm2=0,*commI2=0;
8366       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8367       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8368       const int *comm2Ptr=comm2->getConstPointer();
8369       const int *commI2Ptr=commI2->getConstPointer();
8370       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8371       for(int j=0;j<nbOfGrps2;j++)
8372         {
8373           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8374             {
8375               res->insertAtTheEnd(begin,end);
8376               res->pushBackSilent(-1);
8377             }
8378           else
8379             {
8380               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8381               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8382               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8383               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8384               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8385               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8386               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8387               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8388               const int *idsNodePtr=idsNode->getConstPointer();
8389               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];
8390               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8391               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8392               if(std::abs(norm)>eps)
8393                 {
8394                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8395                   mm3->rotate(center,vec,angle);
8396                 }
8397               mm3->changeSpaceDimension(2);
8398               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8399               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8400               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8401               int nbOfCells=mm4->getNumberOfCells();
8402               for(int k=0;k<nbOfCells;k++)
8403                 {
8404                   int l=0;
8405                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8406                     res->pushBackSilent(idsNodePtr[*work]);
8407                   res->pushBackSilent(-1);
8408                 }
8409             }
8410         }
8411     }
8412   res->popBackSilent();
8413 }
8414
8415 /*!
8416  * 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
8417  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8418  * 
8419  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8420  * \param [in] coords coordinates expected to have 3 components.
8421  * \param [in] begin start of the nodal connectivity of the face.
8422  * \param [in] end end of the nodal connectivity (excluded) of the face.
8423  * \param [out] v the normalized vector of size 3
8424  * \param [out] p the pos of plane
8425  */
8426 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8427 {
8428   std::size_t nbPoints=std::distance(begin,end);
8429   if(nbPoints<3)
8430     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8431   double vec[3]={0.,0.,0.};
8432   std::size_t j=0;
8433   bool refFound=false;
8434   for(;j<nbPoints-1 && !refFound;j++)
8435     {
8436       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8437       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8438       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8439       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8440       if(norm>eps)
8441         {
8442           refFound=true;
8443           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8444         }
8445     }
8446   for(std::size_t i=j;i<nbPoints-1;i++)
8447     {
8448       double curVec[3];
8449       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8450       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8451       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8452       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8453       if(norm<eps)
8454         continue;
8455       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8456       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];
8457       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8458       if(norm>eps)
8459         {
8460           v[0]/=norm; v[1]/=norm; v[2]/=norm;
8461           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8462           return ;
8463         }
8464     }
8465   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8466 }
8467
8468 /*!
8469  * This method tries to obtain a well oriented polyhedron.
8470  * If the algorithm fails, an exception will be thrown.
8471  */
8472 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8473 {
8474   std::list< std::pair<int,int> > edgesOK,edgesFinished;
8475   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8476   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8477   isPerm[0]=true;
8478   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8479   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8480   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8481   //
8482   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8483     {
8484       bgFace=begin;
8485       std::size_t smthChanged=0;
8486       for(std::size_t i=0;i<nbOfFaces;i++)
8487         {
8488           endFace=std::find(bgFace+1,end,-1);
8489           nbOfEdgesInFace=std::distance(bgFace,endFace);
8490           if(!isPerm[i])
8491             {
8492               bool b;
8493               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8494                 {
8495                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8496                   std::pair<int,int> p2(p1.second,p1.first);
8497                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8498                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8499                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8500                 }
8501               if(isPerm[i])
8502                 { 
8503                   if(!b)
8504                     std::reverse(bgFace+1,endFace);
8505                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8506                     {
8507                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8508                       std::pair<int,int> p2(p1.second,p1.first);
8509                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8510                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8511                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8512                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8513                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8514                       if(it!=edgesOK.end())
8515                         {
8516                           edgesOK.erase(it);
8517                           edgesFinished.push_back(p1);
8518                         }
8519                       else
8520                         edgesOK.push_back(p1);
8521                     }
8522                 }
8523             }
8524           bgFace=endFace+1;
8525         }
8526       if(smthChanged==0)
8527         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8528     }
8529   if(!edgesOK.empty())
8530     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8531   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8532     {//not lucky ! The first face was not correctly oriented : reorient all faces...
8533       bgFace=begin;
8534       for(std::size_t i=0;i<nbOfFaces;i++)
8535         {
8536           endFace=std::find(bgFace+1,end,-1);
8537           std::reverse(bgFace+1,endFace);
8538           bgFace=endFace+1;
8539         }
8540     }
8541 }
8542
8543 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8544 {
8545   int nbOfNodesExpected(skin->getNumberOfNodes());
8546   const int *n2oPtr(n2o->getConstPointer());
8547   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8548   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8549   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8550   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8551   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8552   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8553   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_POLYGON;
8554   if(nbOfNodesExpected<1)
8555     return ret.retn();
8556   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8557   *work++=n2oPtr[prevNode];
8558   for(int i=1;i<nbOfNodesExpected;i++)
8559     {
8560       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8561         {
8562           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8563           conn.erase(prevNode);
8564           if(conn.size()==1)
8565             {
8566               int curNode(*(conn.begin()));
8567               *work++=n2oPtr[curNode];
8568               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8569               shar.erase(prevCell);
8570               if(shar.size()==1)
8571                 {
8572                   prevCell=*(shar.begin());
8573                   prevNode=curNode;
8574                 }
8575               else
8576                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8577             }
8578           else
8579             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8580         }
8581       else
8582         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8583     }
8584   return ret.retn();
8585 }
8586
8587 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8588 {
8589   int nbOfNodesExpected(skin->getNumberOfNodes());
8590   int nbOfTurn(nbOfNodesExpected/2);
8591   const int *n2oPtr(n2o->getConstPointer());
8592   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8593   skin->getReverseNodalConnectivity(revNodal,revNodalI);
8594   const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8595   const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8596   const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8597   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8598   int *work(ret->getPointer());  *work++=INTERP_KERNEL::NORM_QPOLYG;
8599   if(nbOfNodesExpected<1)
8600     return ret.retn();
8601   int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8602   *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8603   for(int i=1;i<nbOfTurn;i++)
8604     {
8605       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8606         {
8607           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8608           conn.erase(prevNode);
8609           if(conn.size()==1)
8610             {
8611               int curNode(*(conn.begin()));
8612               *work=n2oPtr[curNode];
8613               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8614               shar.erase(prevCell);
8615               if(shar.size()==1)
8616                 {
8617                   int curCell(*(shar.begin()));
8618                   work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8619                   prevCell=curCell;
8620                   prevNode=curNode;
8621                   work++;
8622                 }
8623               else
8624                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8625             }
8626           else
8627             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8628         }
8629       else
8630         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8631     }
8632   return ret.retn();
8633 }
8634
8635 /*!
8636  * This method makes the assumption spacedimension == meshdimension == 2.
8637  * This method works only for linear cells.
8638  * 
8639  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8640  */
8641 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8642 {
8643   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8644     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8645   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8646   int oldNbOfNodes(skin->getNumberOfNodes());
8647   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8648   int nbOfNodesExpected(skin->getNumberOfNodes());
8649   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8650   int nbCells(skin->getNumberOfCells());
8651   if(nbCells==nbOfNodesExpected)
8652     return buildUnionOf2DMeshLinear(skin,n2o);
8653   else if(2*nbCells==nbOfNodesExpected)
8654     return buildUnionOf2DMeshQuadratic(skin,n2o);
8655   else
8656     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8657 }
8658
8659 /*!
8660  * This method makes the assumption spacedimension == meshdimension == 3.
8661  * This method works only for linear cells.
8662  * 
8663  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8664  */
8665 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8666 {
8667   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8668     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8669   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8670   const int *conn=m->getNodalConnectivity()->getConstPointer();
8671   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8672   int nbOfCells=m->getNumberOfCells();
8673   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8674   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
8675   if(nbOfCells<1)
8676     return ret.retn();
8677   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8678   for(int i=1;i<nbOfCells;i++)
8679     {
8680       *work++=-1;
8681       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8682     }
8683   return ret.retn();
8684 }
8685
8686 /*!
8687  * \brief Creates a graph of cell neighbors
8688  *  \return MEDCouplingSkyLineArray * - an sky line array the user should delete.
8689  *  In the sky line array, graph arcs are stored in terms of (index,value) notation.
8690  *  For example
8691  *  - index:  0 3 5 6 6
8692  *  - value:  1 2 3 2 3 3
8693  *  means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8694  *  Arcs are not doubled but reflexive (1,1) arcs are present for each cell
8695  */
8696 MEDCouplingSkyLineArray *MEDCouplingUMesh::generateGraph() const
8697 {
8698   checkConnectivityFullyDefined();
8699
8700   int meshDim = this->getMeshDimension();
8701   ParaMEDMEM::DataArrayInt* indexr=ParaMEDMEM::DataArrayInt::New();
8702   ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
8703   this->getReverseNodalConnectivity(revConn,indexr);
8704   const int* indexr_ptr=indexr->getConstPointer();
8705   const int* revConn_ptr=revConn->getConstPointer();
8706
8707   const ParaMEDMEM::DataArrayInt* index;
8708   const ParaMEDMEM::DataArrayInt* conn;
8709   conn=this->getNodalConnectivity(); // it includes a type as the 1st element!!!
8710   index=this->getNodalConnectivityIndex();
8711   int nbCells=this->getNumberOfCells();
8712   const int* index_ptr=index->getConstPointer();
8713   const int* conn_ptr=conn->getConstPointer();
8714
8715   //creating graph arcs (cell to cell relations)
8716   //arcs are stored in terms of (index,value) notation
8717   // 0 3 5 6 6
8718   // 1 2 3 2 3 3
8719   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
8720   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
8721
8722   //warning here one node have less than or equal effective number of cell with it
8723   //but cell could have more than effective nodes
8724   //because other equals nodes in other domain (with other global inode)
8725   std::vector <int> cell2cell_index(nbCells+1,0);
8726   std::vector <int> cell2cell;
8727   cell2cell.reserve(3*nbCells);
8728
8729   for (int icell=0; icell<nbCells;icell++)
8730     {
8731       std::map<int,int > counter;
8732       for (int iconn=index_ptr[icell]+1; iconn<index_ptr[icell+1];iconn++)
8733         {
8734           int inode=conn_ptr[iconn];
8735           for (int iconnr=indexr_ptr[inode]; iconnr<indexr_ptr[inode+1];iconnr++)
8736             {
8737               int icell2=revConn_ptr[iconnr];
8738               std::map<int,int>::iterator iter=counter.find(icell2);
8739               if (iter!=counter.end()) (iter->second)++;
8740               else counter.insert(std::make_pair(icell2,1));
8741             }
8742         }
8743       for (std::map<int,int>::const_iterator iter=counter.begin();
8744            iter!=counter.end(); iter++)
8745         if (iter->second >= meshDim)
8746           {
8747             cell2cell_index[icell+1]++;
8748             cell2cell.push_back(iter->first);
8749           }
8750     }
8751   indexr->decrRef();
8752   revConn->decrRef();
8753   cell2cell_index[0]=0;
8754   for (int icell=0; icell<nbCells;icell++)
8755     cell2cell_index[icell+1]=cell2cell_index[icell]+cell2cell_index[icell+1];
8756
8757   //filling up index and value to create skylinearray structure
8758   MEDCouplingSkyLineArray* array=new MEDCouplingSkyLineArray(cell2cell_index,cell2cell);
8759   return array;
8760 }
8761
8762 /*!
8763  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8764  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8765  */
8766 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8767 {
8768   double *w=zipFrmt;
8769   if(spaceDim==3)
8770     for(int i=0;i<nbOfNodesInCell;i++)
8771       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8772   else if(spaceDim==2)
8773     {
8774       for(int i=0;i<nbOfNodesInCell;i++)
8775         {
8776           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8777           *w++=0.;
8778         }
8779     }
8780   else
8781     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8782 }
8783
8784 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8785 {
8786   int nbOfCells=getNumberOfCells();
8787   if(nbOfCells<=0)
8788     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8789   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};
8790   ofs << "  <" << getVTKDataSetType() << ">\n";
8791   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8792   ofs << "      <PointData>\n" << pointData << std::endl;
8793   ofs << "      </PointData>\n";
8794   ofs << "      <CellData>\n" << cellData << std::endl;
8795   ofs << "      </CellData>\n";
8796   ofs << "      <Points>\n";
8797   if(getSpaceDimension()==3)
8798     _coords->writeVTK(ofs,8,"Points",byteData);
8799   else
8800     {
8801       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8802       coo->writeVTK(ofs,8,"Points",byteData);
8803     }
8804   ofs << "      </Points>\n";
8805   ofs << "      <Cells>\n";
8806   const int *cPtr=_nodal_connec->getConstPointer();
8807   const int *cIPtr=_nodal_connec_index->getConstPointer();
8808   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8809   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8810   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8811   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8812   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8813   int szFaceOffsets=0,szConn=0;
8814   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8815     {
8816       *w2=cPtr[cIPtr[i]];
8817       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8818         {
8819           *w1=-1;
8820           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8821           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8822         }
8823       else
8824         {
8825           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8826           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8827           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8828           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8829           w4=std::copy(c.begin(),c.end(),w4);
8830         }
8831     }
8832   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8833   types->writeVTK(ofs,8,"UInt8","types",byteData);
8834   offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8835   if(szFaceOffsets!=0)
8836     {//presence of Polyhedra
8837       connectivity->reAlloc(szConn);
8838       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8839       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8840       w1=faces->getPointer();
8841       for(int i=0;i<nbOfCells;i++)
8842         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8843           {
8844             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8845             *w1++=nbFaces;
8846             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8847             for(int j=0;j<nbFaces;j++)
8848               {
8849                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8850                 *w1++=(int)std::distance(w6,w5);
8851                 w1=std::copy(w6,w5,w1);
8852                 w6=w5+1;
8853               }
8854           }
8855       faces->writeVTK(ofs,8,"Int32","faces",byteData);
8856     }
8857   connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8858   ofs << "      </Cells>\n";
8859   ofs << "    </Piece>\n";
8860   ofs << "  </" << getVTKDataSetType() << ">\n";
8861 }
8862
8863 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8864 {
8865   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8866   if(_mesh_dim==-2)
8867     { stream << " Not set !"; return ; }
8868   stream << " Mesh dimension : " << _mesh_dim << ".";
8869   if(_mesh_dim==-1)
8870     return ;
8871   if(!_coords)
8872     { stream << " No coordinates set !"; return ; }
8873   if(!_coords->isAllocated())
8874     { stream << " Coordinates set but not allocated !"; return ; }
8875   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8876   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8877   if(!_nodal_connec_index)
8878     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8879   if(!_nodal_connec_index->isAllocated())
8880     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8881   int lgth=_nodal_connec_index->getNumberOfTuples();
8882   int cpt=_nodal_connec_index->getNumberOfComponents();
8883   if(cpt!=1 || lgth<1)
8884     return ;
8885   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8886 }
8887
8888 std::string MEDCouplingUMesh::getVTKDataSetType() const
8889 {
8890   return std::string("UnstructuredGrid");
8891 }
8892
8893 std::string MEDCouplingUMesh::getVTKFileExtension() const
8894 {
8895   return std::string("vtu");
8896 }
8897
8898 /*!
8899  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8900  * returns a result mesh constituted by polygons.
8901  * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8902  * all nodes from m2.
8903  * The meshes should be in 2D space. In
8904  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8905  * meshes.
8906  *  \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
8907  *                      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)
8908  *  \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
8909  *                      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)
8910  *  \param [in] eps - precision used to detect coincident mesh entities.
8911  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8912  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8913  *         this array using decrRef() as it is no more needed.
8914  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8915  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8916  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8917  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8918  *         it is no more needed.  
8919  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8920  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8921  *         is no more needed.  
8922  *  \throw If the coordinates array is not set in any of the meshes.
8923  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8924  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8925  *
8926  *  \sa conformize2D, mergeNodes
8927  */
8928 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8929                                                       double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8930 {
8931   if(!m1 || !m2)
8932     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes : input meshes must be not NULL !");
8933   m1->checkFullyDefined();
8934   m2->checkFullyDefined();
8935   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8936     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8937
8938   // Step 1: compute all edge intersections (new nodes)
8939   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8940   MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8941   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8942   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
8943   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8944                               m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8945                               addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8946   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8947   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8948   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8949
8950   // Step 2: re-order newly created nodes according to the ordering found in m2
8951   std::vector< std::vector<int> > intersectEdge2;
8952   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8953   subDiv2.clear(); dd5=0; dd6=0;
8954
8955   // Step 3:
8956   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8957   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8958   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8959                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8960
8961   // Step 4: Prepare final result:
8962   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
8963   addCooDa->alloc((int)(addCoo.size())/2,2);
8964   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8965   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa(DataArrayDouble::New());
8966   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8967   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8968   std::vector<const DataArrayDouble *> coordss(4);
8969   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8970   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(coordss));
8971   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("Intersect2D",2));
8972   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8973   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI(DataArrayInt::New()); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8974   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1(DataArrayInt::New()); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8975   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2(DataArrayInt::New()); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8976   ret->setConnectivity(conn,connI,true);
8977   ret->setCoords(coo);
8978   cellNb1=c1.retn(); cellNb2=c2.retn();
8979   return ret.retn();
8980 }
8981
8982 /// @cond INTERNAL
8983
8984 bool IsColinearOfACellOf(const std::vector< std::vector<int> >& intersectEdge1, const std::vector<int>& candidates, int start, int stop, int& retVal)
8985 {
8986   if(candidates.empty())
8987     return false;
8988   for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8989     {
8990       const std::vector<int>& pool(intersectEdge1[*it]);
8991       int tmp[2]; tmp[0]=start; tmp[1]=stop;
8992       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8993         {
8994           retVal=*it+1;
8995           return true;
8996         }
8997       tmp[0]=stop; tmp[1]=start;
8998       if(std::search(pool.begin(),pool.end(),tmp,tmp+2)!=pool.end())
8999         {
9000           retVal=-*it-1;
9001           return true;
9002         }
9003     }
9004   return false;
9005 }
9006
9007 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,
9008                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInRetColinear, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsInMesh1DForIdsInRetColinear)
9009 {
9010   idsInRetColinear=DataArrayInt::New(); idsInRetColinear->alloc(0,1);
9011   idsInMesh1DForIdsInRetColinear=DataArrayInt::New(); idsInMesh1DForIdsInRetColinear->alloc(0,1);
9012   int nCells(mesh1D->getNumberOfCells());
9013   if(nCells!=(int)intersectEdge2.size())
9014     throw INTERP_KERNEL::Exception("BuildMesh1DCutFrom : internal error # 1 !");
9015   const DataArrayDouble *coo2(mesh1D->getCoords());
9016   const int *c(mesh1D->getNodalConnectivity()->begin()),*ci(mesh1D->getNodalConnectivityIndex()->begin());
9017   const double *coo2Ptr(coo2->begin());
9018   int offset1(coords1->getNumberOfTuples());
9019   int offset2(offset1+coo2->getNumberOfTuples());
9020   int offset3(offset2+addCoo.size()/2);
9021   std::vector<double> addCooQuad;
9022   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cOut(DataArrayInt::New()),ciOut(DataArrayInt::New()); cOut->alloc(0,1); ciOut->alloc(1,1); ciOut->setIJ(0,0,0);
9023   int tmp[4],cicnt(0),kk(0);
9024   for(int i=0;i<nCells;i++)
9025     {
9026       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9027       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coo2Ptr,m));
9028       const std::vector<int>& subEdges(intersectEdge2[i]);
9029       int nbSubEdge(subEdges.size()/2);
9030       for(int j=0;j<nbSubEdge;j++,kk++)
9031         {
9032           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));
9033           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e2(e->buildEdgeLyingOnMe(n1,n2));
9034           INTERP_KERNEL::Edge *e2Ptr(e2);
9035           std::map<int,int>::const_iterator itm;
9036           if(dynamic_cast<INTERP_KERNEL::EdgeArcCircle *>(e2Ptr))
9037             {
9038               tmp[0]=INTERP_KERNEL::NORM_SEG3;
9039               itm=mergedNodes.find(subEdges[2*j]);
9040               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9041               itm=mergedNodes.find(subEdges[2*j+1]);
9042               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9043               tmp[3]=offset3+(int)addCooQuad.size()/2;
9044               double tmp2[2];
9045               e2->getBarycenter(tmp2); addCooQuad.insert(addCooQuad.end(),tmp2,tmp2+2);
9046               cicnt+=4;
9047               cOut->insertAtTheEnd(tmp,tmp+4);
9048               ciOut->pushBackSilent(cicnt);
9049             }
9050           else
9051             {
9052               tmp[0]=INTERP_KERNEL::NORM_SEG2;
9053               itm=mergedNodes.find(subEdges[2*j]);
9054               tmp[1]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j];
9055               itm=mergedNodes.find(subEdges[2*j+1]);
9056               tmp[2]=itm!=mergedNodes.end()?(*itm).second:subEdges[2*j+1];
9057               cicnt+=3;
9058               cOut->insertAtTheEnd(tmp,tmp+3);
9059               ciOut->pushBackSilent(cicnt);
9060             }
9061           int tmp00;
9062           if(IsColinearOfACellOf(intersectEdge1,colinear2[i],tmp[1],tmp[2],tmp00))
9063             {
9064               idsInRetColinear->pushBackSilent(kk);
9065               idsInMesh1DForIdsInRetColinear->pushBackSilent(tmp00);
9066             }
9067         }
9068       e->decrRef();
9069     }
9070   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New(mesh1D->getName(),1));
9071   ret->setConnectivity(cOut,ciOut,true);
9072   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr3(DataArrayDouble::New());
9073   arr3->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9074   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr4(DataArrayDouble::New()); arr4->useArray(&addCooQuad[0],false,C_DEALLOC,(int)addCooQuad.size()/2,2);
9075   std::vector<const DataArrayDouble *> coordss(4);
9076   coordss[0]=coords1; coordss[1]=mesh1D->getCoords(); coordss[2]=arr3; coordss[3]=arr4;
9077   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::Aggregate(coordss));
9078   ret->setCoords(arr);
9079   return ret.retn();
9080 }
9081
9082 MEDCouplingUMesh *BuildRefined2DCellLinear(const DataArrayDouble *coords, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9083 {
9084   std::vector<int> allEdges;
9085   for(const int *it2(descBg);it2!=descEnd;it2++)
9086     {
9087       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9088       if(*it2>0)
9089         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9090       else
9091         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9092     }
9093   std::size_t nb(allEdges.size());
9094   if(nb%2!=0)
9095     throw INTERP_KERNEL::Exception("BuildRefined2DCellLinear : internal error 1 !");
9096   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9097   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9098   ret->setCoords(coords);
9099   ret->allocateCells(1);
9100   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9101   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9102     connOut[kk]=allEdges[2*kk];
9103   ret->insertNextCell(INTERP_KERNEL::NORM_POLYGON,connOut.size(),&connOut[0]);
9104   return ret.retn();
9105 }
9106
9107 MEDCouplingUMesh *BuildRefined2DCellQuadratic(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9108 {
9109   const int *c(mesh2D->getNodalConnectivity()->begin()),*ci(mesh2D->getNodalConnectivityIndex()->begin());
9110   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[cellIdInMesh2D]]));
9111   std::size_t ii(0);
9112   unsigned sz(cm.getNumberOfSons2(c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1));
9113   if(sz!=std::distance(descBg,descEnd))
9114     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 1 !");
9115   INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]]);
9116   std::vector<int> allEdges,centers;
9117   const double *coordsPtr(coords->begin());
9118   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
9119   int offset(coords->getNumberOfTuples());
9120   for(const int *it2(descBg);it2!=descEnd;it2++,ii++)
9121     {
9122       INTERP_KERNEL::NormalizedCellType typeOfSon;
9123       cm.fillSonCellNodalConnectivity2(ii,c+ci[cellIdInMesh2D]+1,ci[cellIdInMesh2D+1]-ci[cellIdInMesh2D]-1,tmpPtr,typeOfSon);
9124       const std::vector<int>& edge1(intersectEdge1[std::abs(*it2)-1]);
9125       if(*it2>0)
9126         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9127       else
9128         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9129       if(edge1.size()==2)
9130         centers.push_back(tmpPtr[2]);//special case where no subsplit of edge -> reuse the original center.
9131       else
9132         {//the current edge has been subsplit -> create corresponding centers.
9133           std::size_t nbOfCentersToAppend(edge1.size()/2);
9134           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9135           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpPtr,coordsPtr,m));
9136           std::vector<int>::const_iterator it3(allEdges.end()-edge1.size());
9137           for(std::size_t k=0;k<nbOfCentersToAppend;k++)
9138             {
9139               double tmpp[2];
9140               const double *aa(coordsPtr+2*(*it3++));
9141               const double *bb(coordsPtr+2*(*it3++));
9142               ee->getMiddleOfPoints(aa,bb,tmpp);
9143               addCoo->insertAtTheEnd(tmpp,tmpp+2);
9144               centers.push_back(offset+k);
9145             }
9146         }
9147     }
9148   std::size_t nb(allEdges.size());
9149   if(nb%2!=0)
9150     throw INTERP_KERNEL::Exception("BuildRefined2DCellQuadratic : internal error 2 !");
9151   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9152   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret(MEDCouplingUMesh::New("",2));
9153   if(addCoo->empty())
9154     ret->setCoords(coords);
9155   else
9156     {
9157       addCoo->rearrange(2);
9158       addCoo=DataArrayDouble::Aggregate(coords,addCoo);
9159       ret->setCoords(addCoo);
9160     }
9161   ret->allocateCells(1);
9162   std::vector<int> connOut(nbOfEdgesOf2DCellSplit);
9163   for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9164     connOut[kk]=allEdges[2*kk];
9165   connOut.insert(connOut.end(),centers.begin(),centers.end());
9166   ret->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,connOut.size(),&connOut[0]);
9167   return ret.retn();
9168 }
9169
9170 /*!
9171  * This method creates a refinement of a cell in \a mesh2D. Those cell is defined by descending connectivity and the sorted subdivided nodal connectivity
9172  * of those edges.
9173  *
9174  * \param [in] mesh2D - The origin 2D mesh. \b Warning \b coords are not those of \a mesh2D. But mesh2D->getCoords()==coords[:mesh2D->getNumberOfNodes()]
9175  */
9176 MEDCouplingUMesh *BuildRefined2DCell(const DataArrayDouble *coords, const MEDCouplingUMesh *mesh2D, int cellIdInMesh2D, const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1)
9177 {
9178   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(mesh2D->getTypeOfCell(cellIdInMesh2D)));
9179   if(!cm.isQuadratic())
9180     return BuildRefined2DCellLinear(coords,descBg,descEnd,intersectEdge1);
9181   else
9182     return BuildRefined2DCellQuadratic(coords,mesh2D,cellIdInMesh2D,descBg,descEnd,intersectEdge1);
9183 }
9184
9185 void AddCellInMesh2D(MEDCouplingUMesh *mesh2D, const std::vector<int>& conn, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edges)
9186 {
9187   bool isQuad(false);
9188   for(std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >::const_iterator it=edges.begin();it!=edges.end();it++)
9189     {
9190       const INTERP_KERNEL::Edge *ee(*it);
9191       if(dynamic_cast<const INTERP_KERNEL::EdgeArcCircle *>(ee))
9192         isQuad=true;
9193     }
9194   if(!isQuad)
9195     mesh2D->insertNextCell(INTERP_KERNEL::NORM_POLYGON,conn.size(),&conn[0]);
9196   else
9197     {
9198       const double *coo(mesh2D->getCoords()->begin());
9199       std::size_t sz(conn.size());
9200       std::vector<double> addCoo;
9201       std::vector<int> conn2(conn);
9202       int offset(mesh2D->getNumberOfNodes());
9203       for(std::size_t i=0;i<sz;i++)
9204         {
9205           double tmp[2];
9206           edges[(i+1)%sz]->getMiddleOfPoints(coo+2*conn[i],coo+2*conn[(i+1)%sz],tmp);// tony a chier i+1 -> i
9207           addCoo.insert(addCoo.end(),tmp,tmp+2);
9208           conn2.push_back(offset+(int)i);
9209         }
9210       mesh2D->getCoords()->rearrange(1);
9211       mesh2D->getCoords()->pushBackValsSilent(&addCoo[0],&addCoo[0]+addCoo.size());
9212       mesh2D->getCoords()->rearrange(2);
9213       mesh2D->insertNextCell(INTERP_KERNEL::NORM_QPOLYG,conn2.size(),&conn2[0]);
9214     }
9215 }
9216
9217 /*!
9218  * \b WARNING edges in out1 coming from \a splitMesh1D are \b NOT oriented because only used for equation of curve.
9219  *
9220  * This method cuts in 2 parts the input 2D cell given using boundaries description (\a edge1Bis and \a edge1BisPtr) using
9221  * a set of edges defined in \a splitMesh1D.
9222  */
9223 void BuildMesh2DCutInternal2(const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& edge1Bis, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edge1BisPtr,
9224                              std::vector< std::vector<int> >& out0, std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > >& out1)
9225 {
9226   std::size_t nb(edge1Bis.size()/2);
9227   std::size_t nbOfEdgesOf2DCellSplit(nb/2);
9228   int iEnd(splitMesh1D->getNumberOfCells());
9229   if(iEnd==0)
9230     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal2 : internal error ! input 1D mesh must have at least one cell !");
9231   std::size_t ii,jj;
9232   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9233   for(ii=0;ii<nb && edge1Bis[2*ii]!=cSplitPtr[ciSplitPtr[0]+1];ii++);
9234   for(jj=ii;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd-1]+2];jj++);
9235   //
9236   if(jj==nb)
9237     {//the edges splitMesh1D[iStart:iEnd] does not fully cut the current 2D cell -> single output cell
9238       out0.resize(1); out1.resize(1);
9239       std::vector<int>& connOut(out0[0]);
9240       connOut.resize(nbOfEdgesOf2DCellSplit);
9241       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr(out1[0]);
9242       edgesPtr.resize(nbOfEdgesOf2DCellSplit);
9243       for(std::size_t kk=0;kk<nbOfEdgesOf2DCellSplit;kk++)
9244         {
9245           connOut[kk]=edge1Bis[2*kk];
9246           edgesPtr[kk]=edge1BisPtr[2*kk];
9247         }
9248     }
9249   else
9250     {
9251       // [i,iEnd[ contains the
9252       out0.resize(2); out1.resize(2);
9253       std::vector<int>& connOutLeft(out0[0]);
9254       std::vector<int>& connOutRight(out0[1]);//connOutLeft should end with edge1Bis[2*ii] and connOutRight should end with edge1Bis[2*jj+1]
9255       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eleft(out1[0]);
9256       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& eright(out1[1]);
9257       for(std::size_t k=ii;k<jj+1;k++)
9258         { connOutLeft.push_back(edge1Bis[2*k+1]); eleft.push_back(edge1BisPtr[2*k+1]); }
9259       std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > ees(iEnd);
9260       for(int ik=0;ik<iEnd;ik++)
9261         {
9262           std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9263           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cSplitPtr[ciSplitPtr[ik]],cSplitPtr+ciSplitPtr[ik]+1,splitMesh1D->getCoords()->begin(),m));
9264           ees[ik]=ee;
9265         }
9266       for(int ik=iEnd-1;ik>=0;ik--)
9267         connOutLeft.push_back(cSplitPtr[ciSplitPtr[ik]+1]);
9268       for(std::size_t k=jj+1;k<nbOfEdgesOf2DCellSplit+ii;k++)
9269         { connOutRight.push_back(edge1Bis[2*k+1]); eright.push_back(edge1BisPtr[2*k+1]); }
9270       eleft.insert(eleft.end(),ees.rbegin(),ees.rend());
9271       for(int ik=0;ik<iEnd;ik++)
9272         connOutRight.push_back(cSplitPtr[ciSplitPtr[ik]+2]);
9273       eright.insert(eright.end(),ees.begin(),ees.end());
9274     }
9275 }
9276
9277 /// @endcond
9278
9279 /// @cond INTERNAL
9280
9281 struct CellInfo
9282 {
9283 public:
9284   CellInfo() { }
9285   CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9286 public:
9287   std::vector<int> _edges;
9288   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > _edges_ptr;
9289 };
9290
9291 CellInfo::CellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr)
9292 {
9293   std::size_t nbe(edges.size());
9294   std::vector<int> edges2(2*nbe); std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edgesPtr2(2*nbe);
9295   for(std::size_t i=0;i<nbe;i++)
9296     {
9297       edges2[2*i]=edges[i]; edges2[2*i+1]=edges[(i+1)%nbe];
9298       edgesPtr2[2*i]=edgesPtr[(i+1)%nbe]; edgesPtr2[2*i+1]=edgesPtr[(i+1)%nbe];//tony a chier
9299     }
9300   _edges.resize(4*nbe); _edges_ptr.resize(4*nbe);
9301   std::copy(edges2.begin(),edges2.end(),_edges.begin()); std::copy(edges2.begin(),edges2.end(),_edges.begin()+2*nbe);
9302   std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()); std::copy(edgesPtr2.begin(),edgesPtr2.end(),_edges_ptr.begin()+2*nbe);
9303 }
9304
9305 class EdgeInfo
9306 {
9307 public:
9308   EdgeInfo(int istart, int iend, const MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>& mesh):_istart(istart),_iend(iend),_mesh(mesh),_left(-7),_right(-7) { }
9309   EdgeInfo(int istart, int iend, int pos, const MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge>& edge):_istart(istart),_iend(iend),_edge(edge),_left(pos),_right(pos+1) { }
9310   bool isInMyRange(int pos) const { return pos>=_istart && pos<_iend; }
9311   void somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9312   void feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const;
9313 private:
9314   int _istart;
9315   int _iend;
9316   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _mesh;
9317   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> _edge;
9318   int _left;
9319   int _right;
9320 };
9321
9322 void EdgeInfo::somethingHappendAt(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9323 {
9324   const MEDCouplingUMesh *mesh(_mesh);
9325   if(mesh)
9326     return ;
9327   if(_right<pos)
9328     return ;
9329   if(_left>pos)
9330     { _left++; _right++; return ; }
9331   if(_right==pos)
9332     {
9333       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9334       if((isLeft && isRight) || (!isLeft && !isRight))
9335         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 1 !");
9336       if(isLeft)
9337         return ;
9338       if(isRight)
9339         {
9340           _right++;
9341           return ;
9342         }
9343     }
9344   if(_left==pos)
9345     {
9346       bool isLeft(std::find(newLeft.begin(),newLeft.end(),_edge)!=newLeft.end()),isRight(std::find(newRight.begin(),newRight.end(),_edge)!=newRight.end());
9347       if((isLeft && isRight) || (!isLeft && !isRight))
9348         throw INTERP_KERNEL::Exception("EdgeInfo::somethingHappendAt : internal error # 2 !");
9349       if(isLeft)
9350         {
9351           _right++;
9352           return ;
9353         }
9354       if(isRight)
9355         {
9356           _left++;
9357           _right++;
9358           return ;
9359         }
9360     }
9361 }
9362
9363 void EdgeInfo::feedEdgeInfoAt(double eps, const MEDCouplingUMesh *mesh2D, int offset, int neighbors[2]) const
9364 {
9365   const MEDCouplingUMesh *mesh(_mesh);
9366   if(!mesh)
9367     {
9368       neighbors[0]=offset+_left; neighbors[1]=offset+_right;
9369     }
9370   else
9371     {// not fully splitting cell case
9372       if(mesh2D->getNumberOfCells()==1)
9373         {//little optimization. 1 cell no need to find in which cell mesh is !
9374           neighbors[0]=offset; neighbors[1]=offset;
9375           return;
9376         }
9377       else
9378         {
9379           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9380           int cellId(mesh2D->getCellContainingPoint(barys->begin(),eps));
9381           if(cellId==-1)
9382             throw INTERP_KERNEL::Exception("EdgeInfo::feedEdgeInfoAt : internal error !");
9383           neighbors[0]=offset+cellId; neighbors[1]=offset+cellId;
9384         }
9385     }
9386 }
9387
9388 class VectorOfCellInfo
9389 {
9390 public:
9391   VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr);
9392   std::size_t size() const { return _pool.size(); }
9393   int getPositionOf(double eps, const MEDCouplingUMesh *mesh) const;
9394   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);
9395   const std::vector<int>& getConnOf(int pos) const { return get(pos)._edges; }
9396   const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& getEdgePtrOf(int pos) const { return get(pos)._edges_ptr; }
9397   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> getZeMesh() const { return _ze_mesh; }
9398   void feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const;
9399 private:
9400   int getZePosOfEdgeGivenItsGlobalId(int pos) const;
9401   void updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight);
9402   const CellInfo& get(int pos) const;
9403   CellInfo& get(int pos);
9404 private:
9405   std::vector<CellInfo> _pool;
9406   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> _ze_mesh;
9407   std::vector<EdgeInfo> _edge_info;
9408 };
9409
9410 VectorOfCellInfo::VectorOfCellInfo(const std::vector<int>& edges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& edgesPtr):_pool(1)
9411 {
9412   _pool[0]._edges=edges;
9413   _pool[0]._edges_ptr=edgesPtr;
9414 }
9415
9416 int VectorOfCellInfo::getPositionOf(double eps, const MEDCouplingUMesh *mesh) const
9417 {
9418   if(_pool.empty())
9419     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : empty !");
9420   if(_pool.size()==1)
9421     return 0;
9422   const MEDCouplingUMesh *zeMesh(_ze_mesh);
9423   if(!zeMesh)
9424     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::getPositionOf : null aggregated mesh !");
9425   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> barys(mesh->getBarycenterAndOwner());
9426   return zeMesh->getCellContainingPoint(barys->begin(),eps);
9427 }
9428
9429 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)
9430 {
9431   get(pos);//to check pos
9432   bool isFast(pos==0 && _pool.size()==1);
9433   std::size_t sz(edges.size());
9434   // dealing with edges
9435   if(sz==1)
9436     _edge_info.push_back(EdgeInfo(istart,iend,mesh1DInCase));
9437   else
9438     _edge_info.push_back(EdgeInfo(istart,iend,pos,edgePtrs[0].back()));
9439   //
9440   std::vector<CellInfo> pool(_pool.size()-1+sz);
9441   for(int i=0;i<pos;i++)
9442     pool[i]=_pool[i];
9443   for(std::size_t j=0;j<sz;j++)
9444     pool[pos+j]=CellInfo(edges[j],edgePtrs[j]);
9445   for(int i=pos+1;i<(int)_pool.size();i++)
9446     pool[i+sz-1]=_pool[i];
9447   _pool=pool;
9448   //
9449   if(sz==2)
9450     updateEdgeInfo(pos,edgePtrs[0],edgePtrs[1]);
9451   //
9452   if(isFast)
9453     {
9454       _ze_mesh=mesh;
9455       return ;
9456     }
9457   //
9458   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > ms;
9459   if(pos>0)
9460     {
9461       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(0,pos,true)));
9462       ms.push_back(elt);
9463     }
9464   ms.push_back(mesh);
9465   if(pos<_ze_mesh->getNumberOfCells()-1)
9466   {
9467     MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> elt(static_cast<MEDCouplingUMesh *>(_ze_mesh->buildPartOfMySelf2(pos+1,_ze_mesh->getNumberOfCells(),true)));
9468     ms.push_back(elt);
9469   }
9470   std::vector< const MEDCouplingUMesh *> ms2(ms.size());
9471   for(std::size_t j=0;j<ms2.size();j++)
9472     ms2[j]=ms[j];
9473   _ze_mesh=MEDCouplingUMesh::MergeUMeshesOnSameCoords(ms2);
9474 }
9475
9476 void VectorOfCellInfo::feedEdgeInfoAt(double eps, int pos, int offset, int neighbors[2]) const
9477 {
9478   _edge_info[getZePosOfEdgeGivenItsGlobalId(pos)].feedEdgeInfoAt(eps,_ze_mesh,offset,neighbors);
9479 }
9480
9481 int VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId(int pos) const
9482 {
9483   if(pos<0)
9484     throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id ! Must be >=0 !");
9485   int ret(0);
9486   for(std::vector<EdgeInfo>::const_iterator it=_edge_info.begin();it!=_edge_info.end();it++,ret++)
9487     {
9488       if((*it).isInMyRange(pos))
9489         return ret;
9490     }
9491   throw INTERP_KERNEL::Exception("VectorOfCellInfo::getZePosOfEdgeGivenItsGlobalId : invalid id !");
9492 }
9493
9494 void VectorOfCellInfo::updateEdgeInfo(int pos, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newLeft, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& newRight)
9495 {
9496   get(pos);//to check;
9497   if(_edge_info.empty())
9498     return ;
9499   std::size_t sz(_edge_info.size()-1);
9500   for(std::size_t i=0;i<sz;i++)
9501     _edge_info[i].somethingHappendAt(pos,newLeft,newRight);
9502 }
9503
9504 const CellInfo& VectorOfCellInfo::get(int pos) const
9505 {
9506   if(pos<0 || pos>=(int)_pool.size())
9507     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get const : invalid pos !");
9508   return _pool[pos];
9509 }
9510
9511 CellInfo& VectorOfCellInfo::get(int pos)
9512 {
9513   if(pos<0 || pos>=(int)_pool.size())
9514     throw INTERP_KERNEL::Exception("VectorOfCellSplitter::get : invalid pos !");
9515   return _pool[pos];
9516 }
9517
9518 /*!
9519  * Given :
9520  * - a \b closed set of edges ( \a allEdges and \a allEdgesPtr ) that defines the split descending 2D cell.
9521  * - \a splitMesh1D a split 2D curve mesh contained into 2D cell defined above.
9522  *
9523  * This method returns the 2D mesh and feeds \a idsLeftRight using offset.
9524  *
9525  * Algorithm : \a splitMesh1D is cut into contiguous parts. Each contiguous parts will build incrementally the output 2D cells.
9526  *
9527  * \param [in] allEdges a list of pairs (beginNode, endNode). Linked with \a allEdgesPtr to get the equation of edge.
9528  */
9529 MEDCouplingUMesh *BuildMesh2DCutInternal(double eps, const MEDCouplingUMesh *splitMesh1D, const std::vector<int>& allEdges, const std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> >& allEdgesPtr, int offset,
9530                                          MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9531 {
9532   int nbCellsInSplitMesh1D(splitMesh1D->getNumberOfCells());
9533   if(nbCellsInSplitMesh1D==0)
9534     throw INTERP_KERNEL::Exception("BuildMesh2DCutInternal : internal error ! input 1D mesh must have at least one cell !");
9535   const int *cSplitPtr(splitMesh1D->getNodalConnectivity()->begin()),*ciSplitPtr(splitMesh1D->getNodalConnectivityIndex()->begin());
9536   std::size_t nb(allEdges.size()),jj;
9537   if(nb%2!=0)
9538     throw INTERP_KERNEL::Exception("BuildMesh2DCutFrom : internal error 2 !");
9539   std::vector<int> edge1Bis(nb*2);
9540   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > edge1BisPtr(nb*2);
9541   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin());
9542   std::copy(allEdges.begin(),allEdges.end(),edge1Bis.begin()+nb);
9543   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin());
9544   std::copy(allEdgesPtr.begin(),allEdgesPtr.end(),edge1BisPtr.begin()+nb);
9545   //
9546   idsLeftRight=DataArrayInt::New(); idsLeftRight->alloc(nbCellsInSplitMesh1D*2); idsLeftRight->fillWithValue(-2); idsLeftRight->rearrange(2);
9547   int *idsLeftRightPtr(idsLeftRight->getPointer());
9548   VectorOfCellInfo pool(edge1Bis,edge1BisPtr);
9549   for(int iStart=0;iStart<nbCellsInSplitMesh1D;)
9550     {// split [0:nbCellsInSplitMesh1D) in contiguous parts [iStart:iEnd)
9551       int iEnd(iStart);
9552       for(;iEnd<nbCellsInSplitMesh1D;)
9553         {
9554           for(jj=0;jj<nb && edge1Bis[2*jj+1]!=cSplitPtr[ciSplitPtr[iEnd]+2];jj++);
9555           if(jj!=nb)
9556             break;
9557           else
9558             iEnd++;
9559         }
9560       if(iEnd<nbCellsInSplitMesh1D)
9561         iEnd++;
9562       //
9563       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfSplitMesh1D(static_cast<MEDCouplingUMesh *>(splitMesh1D->buildPartOfMySelf2(iStart,iEnd,1,true)));
9564       int pos(pool.getPositionOf(eps,partOfSplitMesh1D));
9565       //
9566       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh>retTmp(MEDCouplingUMesh::New("",2));
9567       retTmp->setCoords(splitMesh1D->getCoords());
9568       retTmp->allocateCells();
9569
9570       std::vector< std::vector<int> > out0;
9571       std::vector< std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > > out1;
9572
9573       BuildMesh2DCutInternal2(partOfSplitMesh1D,pool.getConnOf(pos),pool.getEdgePtrOf(pos),out0,out1);
9574       for(std::size_t cnt=0;cnt<out0.size();cnt++)
9575         AddCellInMesh2D(retTmp,out0[cnt],out1[cnt]);
9576       pool.setMeshAt(pos,retTmp,iStart,iEnd,partOfSplitMesh1D,out0,out1);
9577       //
9578       iStart=iEnd;
9579     }
9580   for(int mm=0;mm<nbCellsInSplitMesh1D;mm++)
9581     pool.feedEdgeInfoAt(eps,mm,offset,idsLeftRightPtr+2*mm);
9582   return pool.getZeMesh().retn();
9583 }
9584
9585 MEDCouplingUMesh *BuildMesh2DCutFrom(double eps, int cellIdInMesh2D, const MEDCouplingUMesh *mesh2DDesc, const MEDCouplingUMesh *splitMesh1D,
9586                                      const int *descBg, const int *descEnd, const std::vector< std::vector<int> >& intersectEdge1, int offset,
9587                                      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& idsLeftRight)
9588 {
9589   const int *cdescPtr(mesh2DDesc->getNodalConnectivity()->begin()),*cidescPtr(mesh2DDesc->getNodalConnectivityIndex()->begin());
9590   //
9591   std::vector<int> allEdges;
9592   std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> > allEdgesPtr; // for each sub edge in splitMesh2D the uncut Edge object of the original mesh2D
9593   for(const int *it(descBg);it!=descEnd;it++) // for all edges in the descending connectivity of the 2D mesh in relative Fortran mode
9594     {
9595       int edgeId(std::abs(*it)-1);
9596       std::map< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
9597       MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> ee(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)cdescPtr[cidescPtr[edgeId]],cdescPtr+cidescPtr[edgeId]+1,mesh2DDesc->getCoords()->begin(),m));
9598       const std::vector<int>& edge1(intersectEdge1[edgeId]);
9599       if(*it>0)
9600         allEdges.insert(allEdges.end(),edge1.begin(),edge1.end());
9601       else
9602         allEdges.insert(allEdges.end(),edge1.rbegin(),edge1.rend());
9603       std::size_t sz(edge1.size());
9604       for(std::size_t cnt=0;cnt<sz;cnt++)
9605         allEdgesPtr.push_back(ee);
9606     }
9607   //
9608   return BuildMesh2DCutInternal(eps,splitMesh1D,allEdges,allEdgesPtr,offset,idsLeftRight);
9609 }
9610
9611 bool AreEdgeEqual(const double *coo2D, const INTERP_KERNEL::CellModel& typ1, const int *conn1, const INTERP_KERNEL::CellModel& typ2, const int *conn2, double eps)
9612 {
9613   if(!typ1.isQuadratic() && !typ2.isQuadratic())
9614     {//easy case comparison not
9615       return conn1[0]==conn2[0] && conn1[1]==conn2[1];
9616     }
9617   else if(typ1.isQuadratic() && typ2.isQuadratic())
9618     {
9619       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9620       if(!status0)
9621         return false;
9622       if(conn1[2]==conn2[2])
9623         return true;
9624       const double *a(coo2D+2*conn1[2]),*b(coo2D+2*conn2[2]);
9625       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9626       return dist<eps;
9627     }
9628   else
9629     {//only one is quadratic
9630       bool status0(conn1[0]==conn2[0] && conn1[1]==conn2[1]);
9631       if(!status0)
9632         return false;
9633       const double *a(0),*bb(0),*be(0);
9634       if(typ1.isQuadratic())
9635         {
9636           a=coo2D+2*conn1[2]; bb=coo2D+2*conn2[0]; be=coo2D+2*conn2[1];
9637         }
9638       else
9639         {
9640           a=coo2D+2*conn2[2]; bb=coo2D+2*conn1[0]; be=coo2D+2*conn1[1];
9641         }
9642       double b[2]; b[0]=(be[0]+bb[0])/2.; b[1]=(be[1]+bb[1])/2.;
9643       double dist(sqrt((a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1])));
9644       return dist<eps;
9645     }
9646 }
9647
9648 /*!
9649  * This method returns among the cellIds [ \a candidatesIn2DBg , \a candidatesIn2DEnd ) in \a mesh2DSplit those exactly sharing \a cellIdInMesh1DSplitRelative in \a mesh1DSplit.
9650  * \a mesh2DSplit and \a mesh1DSplit are expected to share the coordinates array.
9651  *
9652  * \param [in] cellIdInMesh1DSplitRelative is in Fortran mode using sign to specify direction.
9653  */
9654 int FindRightCandidateAmong(const MEDCouplingUMesh *mesh2DSplit, const int *candidatesIn2DBg, const int *candidatesIn2DEnd, const MEDCouplingUMesh *mesh1DSplit, int cellIdInMesh1DSplitRelative, double eps)
9655 {
9656   if(candidatesIn2DEnd==candidatesIn2DBg)
9657     throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 1 !");
9658   const double *coo(mesh2DSplit->getCoords()->begin());
9659   if(std::distance(candidatesIn2DBg,candidatesIn2DEnd)==1)
9660     return *candidatesIn2DBg;
9661   int edgeId(std::abs(cellIdInMesh1DSplitRelative)-1);
9662   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur1D(static_cast<MEDCouplingUMesh *>(mesh1DSplit->buildPartOfMySelf(&edgeId,&edgeId+1,true)));
9663   if(cellIdInMesh1DSplitRelative<0)
9664     cur1D->changeOrientationOfCells();
9665   const int *c1D(cur1D->getNodalConnectivity()->begin());
9666   const INTERP_KERNEL::CellModel& ref1DType(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c1D[0]));
9667   for(const int *it=candidatesIn2DBg;it!=candidatesIn2DEnd;it++)
9668     {
9669       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> cur2D(static_cast<MEDCouplingUMesh *>(mesh2DSplit->buildPartOfMySelf(it,it+1,true)));
9670       const int *c(cur2D->getNodalConnectivity()->begin()),*ci(cur2D->getNodalConnectivityIndex()->begin());
9671       const INTERP_KERNEL::CellModel &cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[0]]));
9672       unsigned sz(cm.getNumberOfSons2(c+ci[0]+1,ci[1]-ci[0]-1));
9673       INTERP_KERNEL::AutoPtr<int> tmpPtr(new int[ci[1]-ci[0]]);
9674       for(unsigned it2=0;it2<sz;it2++)
9675         {
9676           INTERP_KERNEL::NormalizedCellType typeOfSon;
9677           cm.fillSonCellNodalConnectivity2(it2,c+ci[0]+1,ci[1]-ci[0]-1,tmpPtr,typeOfSon);
9678           const INTERP_KERNEL::CellModel &curCM(INTERP_KERNEL::CellModel::GetCellModel(typeOfSon));
9679           if(AreEdgeEqual(coo,ref1DType,c1D+1,curCM,tmpPtr,eps))
9680             return *it;
9681         }
9682     }
9683   throw INTERP_KERNEL::Exception("FindRightCandidateAmong : internal error 2 ! Unable to find the edge among split cell !");
9684 }
9685
9686 /// @endcond
9687
9688 /*!
9689  * Partitions the first given 2D mesh using the second given 1D mesh as a tool.
9690  * 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
9691  * and finaly, in case of quadratic polygon the centers of edges new nodes.
9692  * The meshes should be in 2D space. In addition, returns two arrays mapping cells of the resulting mesh to cells of the input.
9693  *
9694  * \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
9695  *                      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)
9696  * \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
9697  *                      you can invoke orderConsecutiveCells1D on \a mesh1D.
9698  * \param [in] eps - precision used to perform intersections and localization operations.
9699  * \param [out] splitMesh2D - the result of the split of \a mesh2D mesh.
9700  * \param [out] splitMesh1D - the result of the split of \a mesh1D mesh.
9701  * \param [out] cellIdInMesh2D - the array that gives for each cell id \a i in \a splitMesh2D the id in \a mesh2D it comes from.
9702  *                               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.
9703  * \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
9704  *                               and the cell in \a splitMesh2D on the right for the 2nt component. -1 means no cell.
9705  *                               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.
9706  *
9707  * \sa Intersect2DMeshes, orderConsecutiveCells1D, conformize2D, mergeNodes
9708  */
9709 void MEDCouplingUMesh::Intersect2DMeshWith1DLine(const MEDCouplingUMesh *mesh2D, const MEDCouplingUMesh *mesh1D, double eps, MEDCouplingUMesh *&splitMesh2D, MEDCouplingUMesh *&splitMesh1D, DataArrayInt *&cellIdInMesh2D, DataArrayInt *&cellIdInMesh1D)
9710 {
9711   if(!mesh2D || !mesh1D)
9712     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine : input meshes must be not NULL !");
9713   mesh2D->checkFullyDefined();
9714   mesh1D->checkFullyDefined();
9715   const std::vector<std::string>& compNames(mesh2D->getCoords()->getInfoOnComponents());
9716   if(mesh2D->getMeshDimension()!=2 || mesh2D->getSpaceDimension()!=2 || mesh1D->getMeshDimension()!=1 || mesh1D->getSpaceDimension()!=2)
9717     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshWith1DLine works with mesh2D with spacedim=meshdim=2 and mesh1D with meshdim=1 spaceDim=2 !");
9718   // Step 1: compute all edge intersections (new nodes)
9719   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
9720   std::vector<double> addCoo,addCoordsQuadratic;  // coordinates of newly created nodes
9721   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9722   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9723   //
9724   // Build desc connectivity
9725   DataArrayInt *desc1(DataArrayInt::New()),*descIndx1(DataArrayInt::New()),*revDesc1(DataArrayInt::New()),*revDescIndx1(DataArrayInt::New());
9726   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9727   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1Desc(mesh2D->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1));
9728   std::map<int,int> mergedNodes;
9729   Intersect1DMeshes(m1Desc,mesh1D,eps,intersectEdge1,colinear2,subDiv2,addCoo,mergedNodes);
9730   // use mergeNodes to fix intersectEdge1
9731   for(std::vector< std::vector<int> >::iterator it0=intersectEdge1.begin();it0!=intersectEdge1.end();it0++)
9732     {
9733       std::size_t n((*it0).size()/2);
9734       int eltStart((*it0)[0]),eltEnd((*it0)[2*n-1]);
9735       std::map<int,int>::const_iterator it1;
9736       it1=mergedNodes.find(eltStart);
9737       if(it1!=mergedNodes.end())
9738         (*it0)[0]=(*it1).second;
9739       it1=mergedNodes.find(eltEnd);
9740       if(it1!=mergedNodes.end())
9741         (*it0)[2*n-1]=(*it1).second;
9742     }
9743   //
9744   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa(DataArrayDouble::New());
9745   addCooDa->useArray(&addCoo[0],false,C_DEALLOC,(int)addCoo.size()/2,2);
9746   // Step 2: re-order newly created nodes according to the ordering found in m2
9747   std::vector< std::vector<int> > intersectEdge2;
9748   BuildIntersectEdges(m1Desc,mesh1D,addCoo,subDiv2,intersectEdge2);
9749   subDiv2.clear();
9750   // Step 3: compute splitMesh1D
9751   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear;
9752   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2(DataArrayInt::New()); ret2->alloc(0,1);
9753   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1(BuildMesh1DCutFrom(mesh1D,intersectEdge2,mesh2D->getCoords(),addCoo,mergedNodes,colinear2,intersectEdge1,
9754       idsInRet1Colinear,idsInDescMesh2DForIdsInRetColinear));
9755   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret3(DataArrayInt::New()); ret3->alloc(ret1->getNumberOfCells()*2,1); ret3->fillWithValue(std::numeric_limits<int>::max()); ret3->rearrange(2);
9756   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInRet1NotColinear(idsInRet1Colinear->buildComplement(ret1->getNumberOfCells()));
9757   // deal with cells in mesh2D that are not cut but only some of their edges are
9758   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsInDesc2DToBeRefined(idsInDescMesh2DForIdsInRetColinear->deepCpy());
9759   idsInDesc2DToBeRefined->abs(); idsInDesc2DToBeRefined->applyLin(1,-1);
9760   idsInDesc2DToBeRefined=idsInDesc2DToBeRefined->buildUnique();
9761   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
9762   if(!idsInDesc2DToBeRefined->empty())
9763     {
9764       DataArrayInt *out0(0),*outi0(0);
9765       MEDCouplingUMesh::ExtractFromIndexedArrays(idsInDesc2DToBeRefined->begin(),idsInDesc2DToBeRefined->end(),dd3,dd4,out0,outi0);
9766       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> outi0s(outi0);
9767       out0s=out0;
9768       out0s=out0s->buildUnique();
9769       out0s->sort(true);
9770     }
9771   //
9772   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1NonCol(static_cast<MEDCouplingUMesh *>(ret1->buildPartOfMySelf(idsInRet1NotColinear->begin(),idsInRet1NotColinear->end())));
9773   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> baryRet1(ret1NonCol->getBarycenterAndOwner());
9774   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elts,eltsIndex;
9775   mesh2D->getCellsContainingPoints(baryRet1->begin(),baryRet1->getNumberOfTuples(),eps,elts,eltsIndex);
9776   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex2(eltsIndex->deltaShiftIndex());
9777   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsIndex3(eltsIndex2->getIdsEqual(1));
9778   if(eltsIndex2->count(0)+eltsIndex3->getNumberOfTuples()!=ret1NonCol->getNumberOfCells())
9779     throw INTERP_KERNEL::Exception("Intersect2DMeshWith1DLine : internal error 1 !");
9780   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToBeModified(elts->buildUnique());
9781   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> untouchedCells(cellsToBeModified->buildComplement(mesh2D->getNumberOfCells()));
9782   if((DataArrayInt *)out0s)
9783     untouchedCells=untouchedCells->buildSubstraction(out0s);//if some edges in ret1 are colinear to descending mesh of mesh2D remove cells from untouched one
9784   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > outMesh2DSplit;
9785   // OK all is ready to insert in ret2 mesh
9786   if(!untouchedCells->empty())
9787     {// the most easy part, cells in mesh2D not impacted at all
9788       outMesh2DSplit.push_back(static_cast<MEDCouplingUMesh *>(mesh2D->buildPartOfMySelf(untouchedCells->begin(),untouchedCells->end())));
9789       outMesh2DSplit.back()->setCoords(ret1->getCoords());
9790       ret2->pushBackValsSilent(untouchedCells->begin(),untouchedCells->end());
9791     }
9792   if((DataArrayInt *)out0s)
9793     {// here dealing with cells in out0s but not in cellsToBeModified
9794       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fewModifiedCells(out0s->buildSubstraction(cellsToBeModified));
9795       const int *rdptr(dd3->begin()),*rdiptr(dd4->begin()),*dptr(dd1->begin()),*diptr(dd2->begin());
9796       for(const int *it=fewModifiedCells->begin();it!=fewModifiedCells->end();it++)
9797         {
9798           outMesh2DSplit.push_back(BuildRefined2DCell(ret1->getCoords(),mesh2D,*it,dptr+diptr[*it],dptr+diptr[*it+1],intersectEdge1));
9799           ret1->setCoords(outMesh2DSplit.back()->getCoords());
9800         }
9801       int offset(ret2->getNumberOfTuples());
9802       ret2->pushBackValsSilent(fewModifiedCells->begin(),fewModifiedCells->end());
9803       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3(DataArrayInt::New()); partOfRet3->alloc(2*idsInRet1Colinear->getNumberOfTuples(),1);
9804       partOfRet3->fillWithValue(std::numeric_limits<int>::max()); partOfRet3->rearrange(2);
9805       int kk(0),*ret3ptr(partOfRet3->getPointer());
9806       for(const int *it=idsInDescMesh2DForIdsInRetColinear->begin();it!=idsInDescMesh2DForIdsInRetColinear->end();it++,kk++)
9807         {
9808           int faceId(std::abs(*it)-1);
9809           for(const int *it2=rdptr+rdiptr[faceId];it2!=rdptr+rdiptr[faceId+1];it2++)
9810             {
9811               int tmp(fewModifiedCells->locateValue(*it2));
9812               if(tmp!=-1)
9813                 {
9814                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9815                     ret3ptr[2*kk]=tmp+offset;
9816                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9817                     ret3ptr[2*kk+1]=tmp+offset;
9818                 }
9819               else
9820                 {//the current edge is shared by a 2D cell that will be split just after
9821                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],-(*it))!=dptr+diptr[*it2+1])
9822                     ret3ptr[2*kk]=-(*it2+1);
9823                   if(std::find(dptr+diptr[*it2],dptr+diptr[*it2+1],(*it))!=dptr+diptr[*it2+1])
9824                     ret3ptr[2*kk+1]=-(*it2+1);
9825                 }
9826             }
9827         }
9828       m1Desc->setCoords(ret1->getCoords());
9829       ret1NonCol->setCoords(ret1->getCoords());
9830       ret3->setPartOfValues3(partOfRet3,idsInRet1Colinear->begin(),idsInRet1Colinear->end(),0,2,1,true);
9831       if(!outMesh2DSplit.empty())
9832         {
9833           DataArrayDouble *da(outMesh2DSplit.back()->getCoords());
9834           for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> >::iterator itt=outMesh2DSplit.begin();itt!=outMesh2DSplit.end();itt++)
9835             (*itt)->setCoords(da);
9836         }
9837     }
9838   cellsToBeModified=cellsToBeModified->buildUniqueNotSorted();
9839   for(const int *it=cellsToBeModified->begin();it!=cellsToBeModified->end();it++)
9840     {
9841       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell(elts->getIdsEqual(*it));
9842       idsNonColPerCell->transformWithIndArr(eltsIndex3->begin(),eltsIndex3->end());
9843       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNonColPerCell2(idsInRet1NotColinear->selectByTupleId(idsNonColPerCell->begin(),idsNonColPerCell->end()));
9844       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> partOfMesh1CuttingCur2DCell(static_cast<MEDCouplingUMesh *>(ret1NonCol->buildPartOfMySelf(idsNonColPerCell->begin(),idsNonColPerCell->end())));
9845       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> partOfRet3;
9846       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));
9847       ret3->setPartOfValues3(partOfRet3,idsNonColPerCell2->begin(),idsNonColPerCell2->end(),0,2,1,true);
9848       outMesh2DSplit.push_back(splitOfOneCell);
9849       for(int i=0;i<splitOfOneCell->getNumberOfCells();i++)
9850         ret2->pushBackSilent(*it);
9851     }
9852   //
9853   std::size_t nbOfMeshes(outMesh2DSplit.size());
9854   std::vector<const MEDCouplingUMesh *> tmp(nbOfMeshes);
9855   for(std::size_t i=0;i<nbOfMeshes;i++)
9856     tmp[i]=outMesh2DSplit[i];
9857   //
9858   ret1->getCoords()->setInfoOnComponents(compNames);
9859   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2D(MEDCouplingUMesh::MergeUMeshesOnSameCoords(tmp));
9860   // To finish - filter ret3 - std::numeric_limits<int>::max() -> -1 - negate values must be resolved.
9861   ret3->rearrange(1);
9862   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> edgesToDealWith(ret3->getIdsStrictlyNegative());
9863   for(const int *it=edgesToDealWith->begin();it!=edgesToDealWith->end();it++)
9864     {
9865       int old2DCellId(-ret3->getIJ(*it,0)-1);
9866       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates(ret2->getIdsEqual(old2DCellId));
9867       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
9868     }
9869   ret3->replaceOneValByInThis(std::numeric_limits<int>::max(),-1);
9870   ret3->rearrange(2);
9871   //
9872   splitMesh1D=ret1.retn();
9873   splitMesh2D=ret2D.retn();
9874   cellIdInMesh2D=ret2.retn();
9875   cellIdInMesh1D=ret3.retn();
9876 }
9877
9878 /**
9879  * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
9880  * (newly created) nodes corresponding to the edge intersections.
9881  * Output params:
9882  * @param[out] cr, crI connectivity of the resulting mesh
9883  * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
9884  * TODO: describe input parameters
9885  */
9886 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
9887                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
9888                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
9889                                                          const std::vector<double>& addCoords,
9890                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
9891 {
9892   static const int SPACEDIM=2;
9893   const double *coo1(m1->getCoords()->getConstPointer());
9894   const int *conn1(m1->getNodalConnectivity()->getConstPointer()),*connI1(m1->getNodalConnectivityIndex()->getConstPointer());
9895   int offset1(m1->getNumberOfNodes());
9896   const double *coo2(m2->getCoords()->getConstPointer());
9897   const int *conn2(m2->getNodalConnectivity()->getConstPointer()),*connI2(m2->getNodalConnectivityIndex()->getConstPointer());
9898   int offset2(offset1+m2->getNumberOfNodes());
9899   int offset3(offset2+((int)addCoords.size())/2);
9900   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
9901   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9902   // Here a BBTree on 2D-cells, not on segments:
9903   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
9904   int ncell1(m1->getNumberOfCells());
9905   crI.push_back(0);
9906   for(int i=0;i<ncell1;i++)
9907     {
9908       std::vector<int> candidates2;
9909       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9910       std::map<INTERP_KERNEL::Node *,int> mapp;
9911       std::map<int,INTERP_KERNEL::Node *> mappRev;
9912       INTERP_KERNEL::QuadraticPolygon pol1;
9913       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
9914       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
9915       // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
9916       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
9917       // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
9918       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
9919           desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
9920       //
9921       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
9922       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
9923       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
9924       for(it1.first();!it1.finished();it1.next())
9925         edges1.insert(it1.current()->getPtr());
9926       //
9927       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
9928       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
9929       int ii=0;
9930       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9931         {
9932           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
9933           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
9934           // Complete mapping with elements coming from the current cell it2 in mesh2:
9935           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
9936           // pol2 is the new QP in the final merged result.
9937           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
9938               pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
9939         }
9940       ii=0;
9941       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
9942         {
9943           INTERP_KERNEL::ComposedEdge::InitLocationsWithOther(pol1,pol2s[ii]);
9944           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
9945           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
9946           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9947         }
9948       // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
9949       // by m2 but that we still want to keep in the final result.
9950       if(!edges1.empty())
9951         {
9952           try
9953           {
9954               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
9955           }
9956           catch(INTERP_KERNEL::Exception& e)
9957           {
9958               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();
9959               throw INTERP_KERNEL::Exception(oss.str().c_str());
9960           }
9961         }
9962       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
9963         (*it).second->decrRef();
9964     }
9965 }
9966
9967 /**
9968  * Provides a renumbering of the cells of this (which has to be a piecewise connected 1D line), so that
9969  * the segments of the line are indexed in consecutive order (i.e. cells \a i and \a i+1 are neighbors).
9970  * This doesn't modify the mesh. This method only works using nodal connectivity consideration. Coordinates of nodes are ignored here.
9971  * The caller is to deal with the resulting DataArrayInt.
9972  *  \throw If the coordinate array is not set.
9973  *  \throw If the nodal connectivity of the cells is not defined.
9974  *  \throw If m1 is not a mesh of dimension 2, or m1 is not a mesh of dimension 1
9975  *  \throw If m2 is not a (piecewise) line (i.e. if a point has more than 2 adjacent segments)
9976  *
9977  * \sa DataArrayInt::sortEachPairToMakeALinkedList
9978  */
9979 DataArrayInt *MEDCouplingUMesh::orderConsecutiveCells1D() const
9980 {
9981   checkFullyDefined();
9982   if(getMeshDimension()!=1)
9983     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D works on unstructured mesh with meshdim = 1 !");
9984
9985   // Check that this is a line (and not a more complex 1D mesh) - each point is used at most by 2 segments:
9986   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _d(DataArrayInt::New()),_dI(DataArrayInt::New());
9987   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _rD(DataArrayInt::New()),_rDI(DataArrayInt::New());
9988   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m_points(buildDescendingConnectivity(_d, _dI, _rD, _rDI));
9989   const int *d(_d->getConstPointer()), *dI(_dI->getConstPointer());
9990   const int *rD(_rD->getConstPointer()), *rDI(_rDI->getConstPointer());
9991   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> _dsi(_rDI->deltaShiftIndex());
9992   const int * dsi(_dsi->getConstPointer());
9993   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dsii = _dsi->getIdsNotInRange(0,3);
9994   m_points=0;
9995   if (dsii->getNumberOfTuples())
9996     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orderConsecutiveCells1D only work with a mesh being a (piecewise) connected line!");
9997
9998   int nc(getNumberOfCells());
9999   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> result(DataArrayInt::New());
10000   result->alloc(nc,1);
10001
10002   // set of edges not used so far
10003   std::set<int> edgeSet;
10004   for (int i=0; i<nc; edgeSet.insert(i), i++);
10005
10006   int startSeg=0;
10007   int newIdx=0;
10008   // while we have points with only one neighbor segments
10009   do
10010     {
10011       std::list<int> linePiece;
10012       // fills a list of consecutive segment linked to startSeg. This can go forward or backward.
10013       for (int direction=0;direction<2;direction++) // direction=0 --> forward, direction=1 --> backward
10014         {
10015           // Fill the list forward (resp. backward) from the start segment:
10016           int activeSeg = startSeg;
10017           int prevPointId = -20;
10018           int ptId;
10019           while (!edgeSet.empty())
10020             {
10021               if (!(direction == 1 && prevPointId==-20)) // prevent adding twice startSeg
10022                 {
10023                   if (direction==0)
10024                     linePiece.push_back(activeSeg);
10025                   else
10026                     linePiece.push_front(activeSeg);
10027                   edgeSet.erase(activeSeg);
10028                 }
10029
10030               int ptId1 = d[dI[activeSeg]], ptId2 = d[dI[activeSeg]+1];
10031               ptId = direction ? (ptId1 == prevPointId ? ptId2 : ptId1) : (ptId2 == prevPointId ? ptId1 : ptId2);
10032               if (dsi[ptId] == 1) // hitting the end of the line
10033                 break;
10034               prevPointId = ptId;
10035               int seg1 = rD[rDI[ptId]], seg2 = rD[rDI[ptId]+1];
10036               activeSeg = (seg1 == activeSeg) ? seg2 : seg1;
10037             }
10038         }
10039       // Done, save final piece into DA:
10040       std::copy(linePiece.begin(), linePiece.end(), result->getPointer()+newIdx);
10041       newIdx += linePiece.size();
10042
10043       // identify next valid start segment (one which is not consumed)
10044       if(!edgeSet.empty())
10045         startSeg = *(edgeSet.begin());
10046     }
10047   while (!edgeSet.empty());
10048   return result.retn();
10049 }
10050
10051 /// @cond INTERNAL
10052
10053 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10054 {
10055   MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> nTmp(n); nTmp->incrRef();
10056   std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>::const_iterator it(m.find(nTmp));
10057   if(it==m.end())
10058     throw INTERP_KERNEL::Exception("Internal error in remapping !");
10059   int v((*it).second);
10060   if(v==forbVal0 || v==forbVal1)
10061     return ;
10062   if(std::find(isect.begin(),isect.end(),v)==isect.end())
10063     isect.push_back(v);
10064 }
10065
10066 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
10067 {
10068   int sz(c.size());
10069   if(sz<=1)
10070     return false;
10071   bool presenceOfOn(false);
10072   for(int i=0;i<sz;i++)
10073     {
10074       INTERP_KERNEL::ElementaryEdge *e(c[i]);
10075       if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
10076         continue ;
10077       IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
10078       IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
10079     }
10080   return presenceOfOn;
10081 }
10082
10083 /// @endcond
10084
10085 /**
10086  * 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.
10087  * 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.
10088  * 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.
10089  * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
10090  *
10091  * \return int - the number of new nodes created (in most of cases 0).
10092  * 
10093  * \throw If \a this is not coherent.
10094  * \throw If \a this has not spaceDim equal to 2.
10095  * \throw If \a this has not meshDim equal to 2.
10096  * \throw If some subcells needed to be split are orphan.
10097  * \sa MEDCouplingUMesh::conformize2D
10098  */
10099 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
10100 {
10101   if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
10102     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
10103   desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
10104   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10105     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10106   if(midOpt==0 && midOptI==0)
10107     {
10108       split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
10109       return 0;
10110     }
10111   else if(midOpt!=0 && midOptI!=0)
10112     return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
10113   else
10114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
10115 }
10116
10117 /*!
10118  * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
10119  * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
10120  * 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
10121  * 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).
10122  * 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.
10123  * 
10124  * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
10125  * The modified cells, if any, are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the initial quadraticness of geometric type.
10126  *
10127  * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
10128  * This method expects that all nodes in \a this are not closer than \a eps.
10129  * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
10130  * 
10131  * \param [in] eps the relative error to detect merged edges.
10132  * \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
10133  *                           that the user is expected to deal with.
10134  *
10135  * \throw If \a this is not coherent.
10136  * \throw If \a this has not spaceDim equal to 2.
10137  * \throw If \a this has not meshDim equal to 2.
10138  * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
10139  */
10140 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
10141 {
10142   static const int SPACEDIM=2;
10143   checkCoherency();
10144   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10145     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10146   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
10147   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
10148   const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
10149   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
10150   const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
10151   int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
10152   std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
10153   std::vector<double> addCoo;
10154   BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
10155   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10156   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10157   for(int i=0;i<nDescCell;i++)
10158     {
10159       std::vector<int> candidates;
10160       myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
10161       for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
10162         if(*it>i)
10163           {
10164             std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10165             INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
10166                 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
10167             INTERP_KERNEL::MergePoints merge;
10168             INTERP_KERNEL::QuadraticPolygon c1,c2;
10169             e1->intersectWith(e2,merge,c1,c2);
10170             e1->decrRef(); e2->decrRef();
10171             if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
10172               overlapEdge[i].push_back(*it);
10173             if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
10174               overlapEdge[*it].push_back(i);
10175           }
10176     }
10177   // splitting done. sort intersect point in intersectEdge.
10178   std::vector< std::vector<int> > middle(nDescCell);
10179   int nbOf2DCellsToBeSplit(0);
10180   bool middleNeedsToBeUsed(false);
10181   std::vector<bool> cells2DToTreat(nDescCell,false);
10182   for(int i=0;i<nDescCell;i++)
10183     {
10184       std::vector<int>& isect(intersectEdge[i]);
10185       int sz((int)isect.size());
10186       if(sz>1)
10187         {
10188           std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
10189           INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
10190           e->sortSubNodesAbs(coords,isect);
10191           e->decrRef();
10192         }
10193       if(sz!=0)
10194         {
10195           int idx0(rdi[i]),idx1(rdi[i+1]);
10196           if(idx1-idx0!=1)
10197             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
10198           if(!cells2DToTreat[rd[idx0]])
10199             {
10200               cells2DToTreat[rd[idx0]]=true;
10201               nbOf2DCellsToBeSplit++;
10202             }
10203           // try to reuse at most eventual 'middle' of SEG3
10204           std::vector<int>& mid(middle[i]);
10205           mid.resize(sz+1,-1);
10206           if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
10207             {
10208               middleNeedsToBeUsed=true;
10209               const std::vector<int>& candidates(overlapEdge[i]);
10210               std::vector<int> trueCandidates;
10211               for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
10212                 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
10213                   trueCandidates.push_back(*itc);
10214               int stNode(c[ci[i]+1]),endNode(isect[0]);
10215               for(int j=0;j<sz+1;j++)
10216                 {
10217                   for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
10218                     {
10219                       int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
10220                       if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
10221                         { mid[j]=*itc; break; }
10222                     }
10223                   stNode=endNode;
10224                   endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
10225                 }
10226             }
10227         }
10228     }
10229   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
10230   if(nbOf2DCellsToBeSplit==0)
10231     return ret.retn();
10232   //
10233   int *retPtr(ret->getPointer());
10234   for(int i=0;i<nCell;i++)
10235     if(cells2DToTreat[i])
10236       *retPtr++=i;
10237   //
10238   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
10239   DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
10240   MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
10241   DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
10242   if(middleNeedsToBeUsed)
10243     { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
10244   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
10245   int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
10246   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.
10247   setPartOfMySelf(ret->begin(),ret->end(),*modif);
10248   {
10249     bool areNodesMerged; int newNbOfNodes;
10250     if(nbOfNodesCreated!=0)
10251       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
10252   }
10253   return ret.retn();
10254 }
10255
10256 /*!
10257  * 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.
10258  * 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).
10259  * 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
10260  * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
10261  * 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
10262  * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
10263  *
10264  * 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
10265  * using new instance, idem for coordinates.
10266  *
10267  * 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.
10268  * 
10269  * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
10270  *
10271  * \throw If \a this is not coherent.
10272  * \throw If \a this has not spaceDim equal to 2.
10273  * \throw If \a this has not meshDim equal to 2.
10274  * 
10275  * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
10276  */
10277 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
10278 {
10279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
10280   checkCoherency();
10281   if(getSpaceDimension()!=2 || getMeshDimension()!=2)
10282     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
10283   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10284   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10285   int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
10286   const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
10287   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
10288   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
10289   const double *coords(_coords->begin());
10290   int *newciptr(newci->getPointer());
10291   for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
10292     {
10293       if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
10294         ret->pushBackSilent(i);
10295       newciptr[1]=newc->getNumberOfTuples();
10296     }
10297   //
10298   if(ret->empty())
10299     return ret.retn();
10300   if(!appendedCoords->empty())
10301     {
10302       appendedCoords->rearrange(2);
10303       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
10304       //non const part
10305       setCoords(newCoords);
10306     }
10307   //non const part
10308   setConnectivity(newc,newci,true);
10309   return ret.retn();
10310 }
10311
10312 /*!
10313  * \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.
10314  *                               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.
10315  *                               And for each j in [1,n) intersect[i][2*(j-1)+1]==intersect[i][2*j].
10316  * \param [out] subDiv2 - for each cell in \a m2Desc returns nodes that split it using convention \a m1Desc first, then \a m2Desc, then addCoo
10317  * \param [out] colinear2 - for each cell in \a m2Desc returns the edges in \a m1Desc that are colinear to it.
10318  * \param [out] addCoo - nodes to be append at the end
10319  * \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.
10320  */
10321 void MEDCouplingUMesh::Intersect1DMeshes(const MEDCouplingUMesh *m1Desc, const MEDCouplingUMesh *m2Desc, double eps,
10322                                          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)
10323 {
10324   static const int SPACEDIM=2;
10325   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
10326   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
10327   const int *c1(m1Desc->getNodalConnectivity()->getConstPointer()),*ci1(m1Desc->getNodalConnectivityIndex()->getConstPointer());
10328   // Build BB tree of all edges in the tool mesh (second mesh)
10329   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
10330   const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
10331   int nDescCell1(m1Desc->getNumberOfCells()),nDescCell2(m2Desc->getNumberOfCells());
10332   intersectEdge1.resize(nDescCell1);
10333   colinear2.resize(nDescCell2);
10334   subDiv2.resize(nDescCell2);
10335   BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
10336
10337   std::vector<int> candidates1(1);
10338   int offset1(m1Desc->getNumberOfNodes());
10339   int offset2(offset1+m2Desc->getNumberOfNodes());
10340   for(int i=0;i<nDescCell1;i++)  // for all edges in the first mesh
10341     {
10342       std::vector<int> candidates2; // edges of mesh2 candidate for intersection
10343       myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
10344       if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
10345         {
10346           std::map<INTERP_KERNEL::Node *,int> map1,map2;
10347           // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
10348           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
10349           candidates1[0]=i;
10350           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
10351           // 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
10352           // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
10353           std::set<INTERP_KERNEL::Node *> nodes;
10354           pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
10355           std::size_t szz(nodes.size());
10356           std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
10357           std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
10358           for(std::size_t iii=0;iii<szz;iii++,itt++)
10359             { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
10360           // end of protection
10361           // Performs egde cutting:
10362           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo,mergedNodes);
10363           delete pol2;
10364           delete pol1;
10365         }
10366       else
10367         // Copy the edge (take only the two first points, ie discard quadratic point at this stage)
10368         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i]+3);
10369     }
10370 }
10371
10372 /*!
10373  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
10374  * It builds the descending connectivity of the two meshes, and then using a binary tree
10375  * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
10376  * Documentation about parameters  colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
10377  */
10378 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
10379                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
10380                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
10381                                                    std::vector<double>& addCoo,
10382                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
10383 {
10384   // Build desc connectivity
10385   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
10386   desc2=DataArrayInt::New();
10387   descIndx2=DataArrayInt::New();
10388   revDesc2=DataArrayInt::New();
10389   revDescIndx2=DataArrayInt::New();
10390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
10391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
10392   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
10393   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
10394   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
10395   std::map<int,int> notUsedMap;
10396   Intersect1DMeshes(m1Desc,m2Desc,eps,intersectEdge1,colinear2,subDiv2,addCoo,notUsedMap);
10397   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
10398   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
10399 }
10400
10401 /*!
10402  * This method performs the 2nd step of Partition of 2D mesh.
10403  * This method has 4 inputs :
10404  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
10405  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
10406  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
10407  * 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'
10408  * Nodes end up lying consecutively on a cutted edge.
10409  * \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.
10410  * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
10411  * \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.
10412  * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
10413  * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
10414  */
10415 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
10416                                            const std::vector<double>& addCoo,
10417                                            const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
10418 {
10419   int offset1=m1->getNumberOfNodes();
10420   int ncell=m2->getNumberOfCells();
10421   const int *c=m2->getNodalConnectivity()->getConstPointer();
10422   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
10423   const double *coo=m2->getCoords()->getConstPointer();
10424   const double *cooBis=m1->getCoords()->getConstPointer();
10425   int offset2=offset1+m2->getNumberOfNodes();
10426   intersectEdge.resize(ncell);
10427   for(int i=0;i<ncell;i++,cI++)
10428     {
10429       const std::vector<int>& divs=subDiv[i];
10430       int nnode=cI[1]-cI[0]-1;
10431       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
10432       std::map<INTERP_KERNEL::Node *, int> mapp22;
10433       for(int j=0;j<nnode;j++)
10434         {
10435           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
10436           int nnid=c[(*cI)+j+1];
10437           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
10438           mapp22[nn]=nnid+offset1;
10439         }
10440       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
10441       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
10442         ((*it).second.first)->decrRef();
10443       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
10444       std::map<INTERP_KERNEL::Node *,int> mapp3;
10445       for(std::size_t j=0;j<divs.size();j++)
10446         {
10447           int id=divs[j];
10448           INTERP_KERNEL::Node *tmp=0;
10449           if(id<offset1)
10450             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
10451           else if(id<offset2)
10452             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
10453           else
10454             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
10455           addNodes[j]=tmp;
10456           mapp3[tmp]=id;
10457         }
10458       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
10459       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
10460         (*it)->decrRef();
10461       e->decrRef();
10462     }
10463 }
10464
10465 /*!
10466  * 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).
10467  * 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
10468  * with a plane. The result will be put in 'cut3DSuf' out parameter.
10469  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
10470  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
10471  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
10472  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
10473  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
10474  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
10475  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
10476  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
10477  * \param [out] cut3DSuf input/output param.
10478  */
10479 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
10480                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
10481                                                    const int *desc, const int *descIndx, 
10482                                                    std::vector< std::pair<int,int> >& cut3DSurf)
10483 {
10484   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
10485   int nbOf3DSurfCell=(int)cut3DSurf.size();
10486   for(int i=0;i<nbOf3DSurfCell;i++)
10487     {
10488       std::vector<int> res;
10489       int offset=descIndx[i];
10490       int nbOfSeg=descIndx[i+1]-offset;
10491       for(int j=0;j<nbOfSeg;j++)
10492         {
10493           int edgeId=desc[offset+j];
10494           int status=cut3DCurve[edgeId];
10495           if(status!=-2)
10496             {
10497               if(status>-1)
10498                 res.push_back(status);
10499               else
10500                 {
10501                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
10502                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
10503                 }
10504             }
10505         }
10506       switch(res.size())
10507       {
10508         case 2:
10509           {
10510             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10511             break;
10512           }
10513         case 1:
10514         case 0:
10515           {
10516             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
10517             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
10518             if(res.size()==2)
10519               {
10520                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
10521               }
10522             else
10523               {
10524                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
10525               }
10526             break;
10527           }
10528         default:
10529           {// case when plane is on a multi colinear edge of a polyhedron
10530             if((int)res.size()==2*nbOfSeg)
10531               {
10532                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
10533               }
10534             else
10535               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
10536           }
10537       }
10538     }
10539 }
10540
10541 /*!
10542  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
10543  * 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).
10544  * 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
10545  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
10546  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
10547  * \param desc is the descending connectivity 3D->3DSurf
10548  * \param descIndx is the descending connectivity index 3D->3DSurf
10549  */
10550 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
10551                                                   const int *desc, const int *descIndx,
10552                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
10553 {
10554   checkFullyDefined();
10555   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10556     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
10557   const int *nodal3D=_nodal_connec->getConstPointer();
10558   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
10559   int nbOfCells=getNumberOfCells();
10560   for(int i=0;i<nbOfCells;i++)
10561     {
10562       std::map<int, std::set<int> > m;
10563       int offset=descIndx[i];
10564       int nbOfFaces=descIndx[i+1]-offset;
10565       int start=-1;
10566       int end=-1;
10567       for(int j=0;j<nbOfFaces;j++)
10568         {
10569           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
10570           if(p.first!=-1 && p.second!=-1)
10571             {
10572               if(p.first!=-2)
10573                 {
10574                   start=p.first; end=p.second;
10575                   m[p.first].insert(p.second);
10576                   m[p.second].insert(p.first);
10577                 }
10578               else
10579                 {
10580                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
10581                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
10582                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
10583                   INTERP_KERNEL::NormalizedCellType cmsId;
10584                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
10585                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
10586                   for(unsigned k=0;k<nbOfNodesSon;k++)
10587                     {
10588                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
10589                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
10590                     }
10591                 }
10592             }
10593         }
10594       if(m.empty())
10595         continue;
10596       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
10597       int prev=end;
10598       while(end!=start)
10599         {
10600           std::map<int, std::set<int> >::const_iterator it=m.find(start);
10601           const std::set<int>& s=(*it).second;
10602           std::set<int> s2; s2.insert(prev);
10603           std::set<int> s3;
10604           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
10605           if(s3.size()==1)
10606             {
10607               int val=*s3.begin();
10608               conn.push_back(start);
10609               prev=start;
10610               start=val;
10611             }
10612           else
10613             start=end;
10614         }
10615       conn.push_back(end);
10616       if(conn.size()>3)
10617         {
10618           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
10619           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
10620           cellIds->pushBackSilent(i);
10621         }
10622     }
10623 }
10624
10625 /*!
10626  * 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
10627  * 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
10628  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
10629  * 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
10630  * 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.
10631  * 
10632  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
10633  */
10634 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
10635 {
10636   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
10637   if(sz>=4)
10638     {
10639       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
10640       if(cm.getDimension()==2)
10641         {
10642           const int *node=nodalConnBg+1;
10643           int startNode=*node++;
10644           double refX=coords[2*startNode];
10645           for(;node!=nodalConnEnd;node++)
10646             {
10647               if(coords[2*(*node)]<refX)
10648                 {
10649                   startNode=*node;
10650                   refX=coords[2*startNode];
10651                 }
10652             }
10653           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
10654           refX=1e300;
10655           double tmp1;
10656           double tmp2[2];
10657           double angle0=-M_PI/2;
10658           //
10659           int nextNode=-1;
10660           int prevNode=-1;
10661           double resRef;
10662           double angleNext=0.;
10663           while(nextNode!=startNode)
10664             {
10665               nextNode=-1;
10666               resRef=1e300;
10667               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
10668                 {
10669                   if(*node!=tmpOut.back() && *node!=prevNode)
10670                     {
10671                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
10672                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
10673                       double res;
10674                       if(angleM<=angle0)
10675                         res=angle0-angleM;
10676                       else
10677                         res=angle0-angleM+2.*M_PI;
10678                       if(res<resRef)
10679                         {
10680                           nextNode=*node;
10681                           resRef=res;
10682                           angleNext=angleM;
10683                         }
10684                     }
10685                 }
10686               if(nextNode!=startNode)
10687                 {
10688                   angle0=angleNext-M_PI;
10689                   if(angle0<-M_PI)
10690                     angle0+=2*M_PI;
10691                   prevNode=tmpOut.back();
10692                   tmpOut.push_back(nextNode);
10693                 }
10694             }
10695           std::vector<int> tmp3(2*(sz-1));
10696           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
10697           std::copy(nodalConnBg+1,nodalConnEnd,it);
10698           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
10699             {
10700               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10701               return false;
10702             }
10703           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
10704             {
10705               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
10706               return false;
10707             }
10708           else
10709             {
10710               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
10711               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
10712               return true;
10713             }
10714         }
10715       else
10716         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10717     }
10718   else
10719     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
10720 }
10721
10722 /*!
10723  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
10724  * 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.
10725  * 
10726  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
10727  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
10728  * \param [in,out] arr array in which the remove operation will be done.
10729  * \param [in,out] arrIndx array in the remove operation will modify
10730  * \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])
10731  * \return true if \b arr and \b arrIndx have been modified, false if not.
10732  */
10733 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
10734 {
10735   if(!arrIndx || !arr)
10736     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
10737   if(offsetForRemoval<0)
10738     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
10739   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
10740   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
10741   int *arrIPtr=arrIndx->getPointer();
10742   *arrIPtr++=0;
10743   int previousArrI=0;
10744   const int *arrPtr=arr->getConstPointer();
10745   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
10746   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
10747     {
10748       if(*arrIPtr-previousArrI>offsetForRemoval)
10749         {
10750           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
10751             {
10752               if(s.find(*work)==s.end())
10753                 arrOut.push_back(*work);
10754             }
10755         }
10756       previousArrI=*arrIPtr;
10757       *arrIPtr=(int)arrOut.size();
10758     }
10759   if(arr->getNumberOfTuples()==(int)arrOut.size())
10760     return false;
10761   arr->alloc((int)arrOut.size(),1);
10762   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
10763   return true;
10764 }
10765
10766 /*!
10767  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10768  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
10769  * The selection of extraction is done standardly in new2old format.
10770  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10771  *
10772  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10773  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10774  * \param [in] arrIn arr origin array from which the extraction will be done.
10775  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10776  * \param [out] arrOut the resulting array
10777  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10778  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
10779  */
10780 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10781                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10782 {
10783   if(!arrIn || !arrIndxIn)
10784     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
10785   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10786   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10787     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
10788   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
10789   const int *arrInPtr=arrIn->getConstPointer();
10790   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10791   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10792   if(nbOfGrps<0)
10793     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10794   int maxSizeOfArr=arrIn->getNumberOfTuples();
10795   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10796   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10797   arrIo->alloc((int)(sz+1),1);
10798   const int *idsIt=idsOfSelectBg;
10799   int *work=arrIo->getPointer();
10800   *work++=0;
10801   int lgth=0;
10802   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
10803     {
10804       if(*idsIt>=0 && *idsIt<nbOfGrps)
10805         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
10806       else
10807         {
10808           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10809           throw INTERP_KERNEL::Exception(oss.str().c_str());
10810         }
10811       if(lgth>=work[-1])
10812         *work=lgth;
10813       else
10814         {
10815           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
10816           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
10817           throw INTERP_KERNEL::Exception(oss.str().c_str());
10818         }
10819     }
10820   arro->alloc(lgth,1);
10821   work=arro->getPointer();
10822   idsIt=idsOfSelectBg;
10823   for(std::size_t i=0;i<sz;i++,idsIt++)
10824     {
10825       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
10826         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
10827       else
10828         {
10829           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
10830           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10831           throw INTERP_KERNEL::Exception(oss.str().c_str());
10832         }
10833     }
10834   arrOut=arro.retn();
10835   arrIndexOut=arrIo.retn();
10836 }
10837
10838 /*!
10839  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10840  * 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 ).
10841  * The selection of extraction is done standardly in new2old format.
10842  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
10843  *
10844  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10845  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10846  * \param [in] arrIn arr origin array from which the extraction will be done.
10847  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10848  * \param [out] arrOut the resulting array
10849  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10850  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
10851  */
10852 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10853                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10854 {
10855   if(!arrIn || !arrIndxIn)
10856     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
10857   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
10858   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
10859     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
10860   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
10861   const int *arrInPtr=arrIn->getConstPointer();
10862   const int *arrIndxPtr=arrIndxIn->getConstPointer();
10863   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
10864   if(nbOfGrps<0)
10865     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
10866   int maxSizeOfArr=arrIn->getNumberOfTuples();
10867   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10868   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10869   arrIo->alloc((int)(sz+1),1);
10870   int idsIt=idsOfSelectStart;
10871   int *work=arrIo->getPointer();
10872   *work++=0;
10873   int lgth=0;
10874   for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
10875     {
10876       if(idsIt>=0 && idsIt<nbOfGrps)
10877         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
10878       else
10879         {
10880           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
10881           throw INTERP_KERNEL::Exception(oss.str().c_str());
10882         }
10883       if(lgth>=work[-1])
10884         *work=lgth;
10885       else
10886         {
10887           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
10888           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
10889           throw INTERP_KERNEL::Exception(oss.str().c_str());
10890         }
10891     }
10892   arro->alloc(lgth,1);
10893   work=arro->getPointer();
10894   idsIt=idsOfSelectStart;
10895   for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
10896     {
10897       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
10898         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
10899       else
10900         {
10901           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
10902           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
10903           throw INTERP_KERNEL::Exception(oss.str().c_str());
10904         }
10905     }
10906   arrOut=arro.retn();
10907   arrIndexOut=arrIo.retn();
10908 }
10909
10910 /*!
10911  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10912  * 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
10913  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
10914  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
10915  *
10916  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10917  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10918  * \param [in] arrIn arr origin array from which the extraction will be done.
10919  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10920  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
10921  * \param [in] srcArrIndex index array of \b srcArr
10922  * \param [out] arrOut the resulting array
10923  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
10924  * 
10925  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
10926  */
10927 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
10928                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
10929                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
10930 {
10931   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10932     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
10933   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
10934   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
10935   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10936   std::vector<bool> v(nbOfTuples,true);
10937   int offset=0;
10938   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10939   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10940   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
10941     {
10942       if(*it>=0 && *it<nbOfTuples)
10943         {
10944           v[*it]=false;
10945           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
10946         }
10947       else
10948         {
10949           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
10950           throw INTERP_KERNEL::Exception(oss.str().c_str());
10951         }
10952     }
10953   srcArrIndexPtr=srcArrIndex->getConstPointer();
10954   arrIo->alloc(nbOfTuples+1,1);
10955   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
10956   const int *arrInPtr=arrIn->getConstPointer();
10957   const int *srcArrPtr=srcArr->getConstPointer();
10958   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
10959   int *arroPtr=arro->getPointer();
10960   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
10961     {
10962       if(v[ii])
10963         {
10964           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
10965           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
10966         }
10967       else
10968         {
10969           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
10970           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
10971           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
10972         }
10973     }
10974   arrOut=arro.retn();
10975   arrIndexOut=arrIo.retn();
10976 }
10977
10978 /*!
10979  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
10980  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
10981  *
10982  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
10983  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
10984  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
10985  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
10986  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
10987  * \param [in] srcArrIndex index array of \b srcArr
10988  * 
10989  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
10990  */
10991 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
10992                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
10993 {
10994   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
10995     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
10996   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
10997   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
10998   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
10999   int *arrInOutPtr=arrInOut->getPointer();
11000   const int *srcArrPtr=srcArr->getConstPointer();
11001   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
11002     {
11003       if(*it>=0 && *it<nbOfTuples)
11004         {
11005           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
11006             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
11007           else
11008             {
11009               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] !";
11010               throw INTERP_KERNEL::Exception(oss.str().c_str());
11011             }
11012         }
11013       else
11014         {
11015           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
11016           throw INTERP_KERNEL::Exception(oss.str().c_str());
11017         }
11018     }
11019 }
11020
11021 /*!
11022  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11023  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11024  * 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]].
11025  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11026  * A negative value in \b arrIn means that it is ignored.
11027  * 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.
11028  * 
11029  * \param [in] arrIn arr origin array from which the extraction will be done.
11030  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11031  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11032  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
11033  */
11034 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
11035 {
11036   int seed=0,nbOfDepthPeelingPerformed=0;
11037   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
11038 }
11039
11040 /*!
11041  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
11042  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
11043  * 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]].
11044  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
11045  * A negative value in \b arrIn means that it is ignored.
11046  * 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.
11047  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
11048  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
11049  * \param [in] arrIn arr origin array from which the extraction will be done.
11050  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11051  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
11052  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
11053  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
11054  * \sa MEDCouplingUMesh::partitionBySpreadZone
11055  */
11056 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11057 {
11058   nbOfDepthPeelingPerformed=0;
11059   if(!arrIndxIn)
11060     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
11061   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11062   if(nbOfTuples<=0)
11063     {
11064       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
11065       return ret;
11066     }
11067   //
11068   std::vector<bool> fetched(nbOfTuples,false);
11069   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
11070 }
11071
11072 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
11073 {
11074   nbOfDepthPeelingPerformed=0;
11075   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
11076     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
11077   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11078   std::vector<bool> fetched2(nbOfTuples,false);
11079   int i=0;
11080   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
11081     {
11082       if(*seedElt>=0 && *seedElt<nbOfTuples)
11083         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
11084       else
11085         { 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()); }
11086     }
11087   const int *arrInPtr=arrIn->getConstPointer();
11088   const int *arrIndxPtr=arrIndxIn->getConstPointer();
11089   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
11090   std::vector<int> idsToFetch1(seedBg,seedEnd);
11091   std::vector<int> idsToFetch2;
11092   std::vector<int> *idsToFetch=&idsToFetch1;
11093   std::vector<int> *idsToFetchOther=&idsToFetch2;
11094   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
11095     {
11096       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
11097         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
11098           if(!fetched[*it2])
11099             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
11100       std::swap(idsToFetch,idsToFetchOther);
11101       idsToFetchOther->clear();
11102       nbOfDepthPeelingPerformed++;
11103     }
11104   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
11105   i=0;
11106   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
11107   int *retPtr=ret->getPointer();
11108   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
11109     if(*it)
11110       *retPtr++=i;
11111   return ret.retn();
11112 }
11113
11114 /*!
11115  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11116  * 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
11117  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
11118  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
11119  *
11120  * \param [in] start begin of set of ids of the input extraction (included)
11121  * \param [in] end end of set of ids of the input extraction (excluded)
11122  * \param [in] step step of the set of ids in range mode.
11123  * \param [in] arrIn arr origin array from which the extraction will be done.
11124  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11125  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11126  * \param [in] srcArrIndex index array of \b srcArr
11127  * \param [out] arrOut the resulting array
11128  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
11129  * 
11130  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
11131  */
11132 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
11133                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
11134                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
11135 {
11136   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11137     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
11138   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
11139   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
11140   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11141   int offset=0;
11142   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11143   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11144   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
11145   int it=start;
11146   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11147     {
11148       if(it>=0 && it<nbOfTuples)
11149         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
11150       else
11151         {
11152           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11153           throw INTERP_KERNEL::Exception(oss.str().c_str());
11154         }
11155     }
11156   srcArrIndexPtr=srcArrIndex->getConstPointer();
11157   arrIo->alloc(nbOfTuples+1,1);
11158   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
11159   const int *arrInPtr=arrIn->getConstPointer();
11160   const int *srcArrPtr=srcArr->getConstPointer();
11161   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
11162   int *arroPtr=arro->getPointer();
11163   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
11164     {
11165       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
11166       if(pos<0)
11167         {
11168           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
11169           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
11170         }
11171       else
11172         {
11173           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
11174           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
11175         }
11176     }
11177   arrOut=arro.retn();
11178   arrIndexOut=arrIo.retn();
11179 }
11180
11181 /*!
11182  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
11183  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
11184  *
11185  * \param [in] start begin of set of ids of the input extraction (included)
11186  * \param [in] end end of set of ids of the input extraction (excluded)
11187  * \param [in] step step of the set of ids in range mode.
11188  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
11189  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
11190  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
11191  * \param [in] srcArrIndex index array of \b srcArr
11192  * 
11193  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
11194  */
11195 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
11196                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
11197 {
11198   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
11199     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
11200   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
11201   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
11202   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
11203   int *arrInOutPtr=arrInOut->getPointer();
11204   const int *srcArrPtr=srcArr->getConstPointer();
11205   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
11206   int it=start;
11207   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
11208     {
11209       if(it>=0 && it<nbOfTuples)
11210         {
11211           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
11212             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
11213           else
11214             {
11215               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
11216               throw INTERP_KERNEL::Exception(oss.str().c_str());
11217             }
11218         }
11219       else
11220         {
11221           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
11222           throw INTERP_KERNEL::Exception(oss.str().c_str());
11223         }
11224     }
11225 }
11226
11227 /*!
11228  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
11229  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
11230  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
11231  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
11232  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
11233  * 
11234  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
11235  */
11236 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
11237 {
11238   checkFullyDefined();
11239   int mdim=getMeshDimension();
11240   int spaceDim=getSpaceDimension();
11241   if(mdim!=spaceDim)
11242     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
11243   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
11244   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
11245   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
11246   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
11247   ret->setCoords(getCoords());
11248   ret->allocateCells((int)partition.size());
11249   //
11250   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
11251     {
11252       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
11253       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
11254       switch(mdim)
11255       {
11256         case 2:
11257           cell=tmp->buildUnionOf2DMesh();
11258           break;
11259         case 3:
11260           cell=tmp->buildUnionOf3DMesh();
11261           break;
11262         default:
11263           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
11264       }
11265
11266       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
11267     }
11268   //
11269   ret->finishInsertingCells();
11270   return ret.retn();
11271 }
11272
11273 /*!
11274  * This method partitions \b this into contiguous zone.
11275  * This method only needs a well defined connectivity. Coordinates are not considered here.
11276  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
11277  */
11278 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
11279 {
11280   int nbOfCellsCur=getNumberOfCells();
11281   std::vector<DataArrayInt *> ret;
11282   if(nbOfCellsCur<=0)
11283     return ret;
11284   DataArrayInt *neigh=0,*neighI=0;
11285   computeNeighborsOfCells(neigh,neighI);
11286   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
11287   std::vector<bool> fetchedCells(nbOfCellsCur,false);
11288   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
11289   int seed=0;
11290   while(seed<nbOfCellsCur)
11291     {
11292       int nbOfPeelPerformed=0;
11293       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
11294       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
11295     }
11296   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
11297     ret.push_back((*it).retn());
11298   return ret;
11299 }
11300
11301 /*!
11302  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
11303  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
11304  *
11305  * \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.
11306  * \return a newly allocated DataArrayInt to be managed by the caller.
11307  * \throw In case of \a code has not the right format (typically of size 3*n)
11308  */
11309 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
11310 {
11311   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
11312   std::size_t nb=code.size()/3;
11313   if(code.size()%3!=0)
11314     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
11315   ret->alloc((int)nb,2);
11316   int *retPtr=ret->getPointer();
11317   for(std::size_t i=0;i<nb;i++,retPtr+=2)
11318     {
11319       retPtr[0]=code[3*i+2];
11320       retPtr[1]=code[3*i+2]+code[3*i+1];
11321     }
11322   return ret.retn();
11323 }
11324
11325 /*!
11326  * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
11327  * All cells in \a this are expected to be linear 3D cells.
11328  * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
11329  * It leads to an increase to number of cells.
11330  * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
11331  * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints 
11332  * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
11333  *
11334  * \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.
11335  *                      For all other cells, the splitting policy will be ignored. See INTERP_KERNEL::SplittingPolicy for the images.
11336  * \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. 
11337  * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
11338  *          an id of old cell producing it. The caller is to delete this array using
11339  *         decrRef() as it is no more needed.
11340  * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
11341  *
11342  * \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
11343  * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
11344  * 
11345  * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
11346  * \throw If \a this is not fully constituted with linear 3D cells.
11347  * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
11348  */
11349 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
11350 {
11351   INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
11352   checkConnectivityFullyDefined();
11353   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
11354     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
11355   int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
11356   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
11357   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
11358   int *retPt(ret->getPointer());
11359   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
11360   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
11361   const int *oldc(_nodal_connec->begin());
11362   const int *oldci(_nodal_connec_index->begin());
11363   const double *coords(_coords->begin());
11364   for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
11365     {
11366       std::vector<int> a; std::vector<double> b;
11367       INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
11368       std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
11369       const int *aa(&a[0]);
11370       if(!b.empty())
11371         {
11372           for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
11373             if(*it<0)
11374               *it=(-(*(it))-1+nbNodes);
11375           addPts->insertAtTheEnd(b.begin(),b.end());
11376           nbNodes+=(int)b.size()/3;
11377         }
11378       for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
11379         newConn->insertAtTheEnd(aa,aa+4);
11380     }
11381   if(!addPts->empty())
11382     {
11383       addPts->rearrange(3);
11384       nbOfAdditionalPoints=addPts->getNumberOfTuples();
11385       addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
11386       ret0->setCoords(addPts);
11387     }
11388   else
11389     {
11390       nbOfAdditionalPoints=0;
11391       ret0->setCoords(getCoords());
11392     }
11393   ret0->setNodalConnectivity(newConn);
11394   //
11395   ret->computeOffsets2();
11396   n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
11397   return ret0.retn();
11398 }
11399
11400 /*!
11401  * 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). 
11402  *
11403  * \sa MEDCouplingUMesh::split2DCells
11404  */
11405 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
11406 {
11407   checkConnectivityFullyDefined();
11408   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
11409   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11410   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11411   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11412   int prevPosOfCi(ciPtr[0]);
11413   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11414     {
11415       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
11416       *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
11417       for(int j=0;j<sz;j++)
11418         {
11419           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
11420           for(int k=0;k<sz2;k++)
11421             *cPtr++=subPtr[offset2+k];
11422           if(j!=sz-1)
11423             *cPtr++=oldConn[prevPosOfCi+j+2];
11424           deltaSz+=sz2;
11425         }
11426       prevPosOfCi=ciPtr[1];
11427       ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11428     }
11429   if(c->end()!=cPtr)
11430     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
11431   _nodal_connec->decrRef();
11432   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
11433 }
11434
11435 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11436 {
11437   if(id!=-1)
11438     return id;
11439   else
11440     {
11441       int ret(nodesCnter++);
11442       double newPt[2];
11443       e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
11444       addCoo.insertAtTheEnd(newPt,newPt+2);
11445       return ret;
11446     }
11447 }
11448
11449 int InternalAddPointOriented(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
11450 {
11451   if(id!=-1)
11452     return id;
11453   else
11454     {
11455       int ret(nodesCnter++);
11456       double newPt[2];
11457       e->getMiddleOfPointsOriented(coo+2*startId,coo+2*endId,newPt);
11458       addCoo.insertAtTheEnd(newPt,newPt+2);
11459       return ret;
11460     }
11461 }
11462
11463
11464 /// @cond INTERNAL
11465
11466 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)
11467 {
11468   int tmp[3];
11469   int trueStart(start>=0?start:nbOfEdges+start);
11470   tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
11471   newConnOfCell->insertAtTheEnd(tmp,tmp+3);
11472   if(linOrArc)
11473     {
11474       if(stp-start>1)
11475         {
11476           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11477           InternalAddPointOriented(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
11478           middles.push_back(tmp3+offset);
11479         }
11480       else
11481         middles.push_back(connBg[trueStart+nbOfEdges]);
11482     }
11483 }
11484
11485 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)
11486 {
11487   int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
11488   newConnOfCell->pushBackSilent(tmpEnd);
11489   if(linOrArc)
11490     {
11491       if(stp-start>1)
11492         {
11493           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11494           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11495           middles.push_back(tmp3+offset);
11496         }
11497       else
11498         middles.push_back(connBg[start+nbOfEdges]);
11499     }
11500 }
11501
11502 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)
11503 {
11504   // only the quadratic point to deal with:
11505   if(linOrArc)
11506     {
11507       if(stp-start>1)
11508         {
11509           int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
11510           int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
11511           InternalAddPointOriented(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
11512           middles.push_back(tmp3+offset);
11513         }
11514       else
11515         middles.push_back(connBg[start+nbOfEdges]);
11516     }
11517 }
11518
11519 /// @cond INTERNAL
11520
11521 /*!
11522  * 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 ) .
11523  * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
11524  */
11525 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
11526 {
11527   std::size_t sz(std::distance(connBg,connEnd));
11528   if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
11529     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
11530   sz--;
11531   INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
11532   const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
11533   unsigned nbs(cm.getNumberOfSons2(connBg+1,sz));
11534   unsigned nbOfHit(0); // number of fusions operated
11535   int posBaseElt(0),posEndElt(0),nbOfTurn(0);
11536   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
11537   INTERP_KERNEL::NormalizedCellType typeOfSon;
11538   std::vector<int> middles;
11539   bool ret(false);
11540   for(;(nbOfTurn+nbOfHit)<nbs;nbOfTurn++)
11541     {
11542       cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
11543       std::map<MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node>,int> m;
11544       INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11545       posEndElt = posBaseElt+1;
11546
11547       // Look backward first: are the final edges of the cells colinear with the first ones?
11548       // This initializes posBaseElt.
11549       if(nbOfTurn==0)
11550         {
11551           for(unsigned i=1;i<nbs && nbOfHit<maxNbOfHit;i++) // 2nd condition is to avoid ending with a cell wih one single edge
11552             {
11553               cm.fillSonCellNodalConnectivity2(nbs-i,connBg+1,sz,tmpConn,typeOfSon);
11554               INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11555               INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11556               bool isColinear=eint->areColinears();
11557               if(isColinear)
11558                 {
11559                   nbOfHit++;
11560                   posBaseElt--;
11561                   ret=true;
11562                 }
11563               delete eint;
11564               eCand->decrRef();
11565               if(!isColinear)
11566                 break;
11567             }
11568         }
11569       // Now move forward:
11570       const unsigned fwdStart = (nbOfTurn == 0 ? 0 : posBaseElt);  // the first element to be inspected going forward
11571       for(unsigned j=fwdStart+1;j<nbs && nbOfHit<maxNbOfHit;j++)  // 2nd condition is to avoid ending with a cell wih one single edge
11572         {
11573           cm.fillSonCellNodalConnectivity2((int)j,connBg+1,sz,tmpConn,typeOfSon); // get edge #j's connectivity
11574           INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
11575           INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
11576           bool isColinear(eint->areColinears());
11577           if(isColinear)
11578             {
11579               nbOfHit++;
11580               posEndElt++;
11581               ret=true;
11582             }
11583           delete eint;
11584           eCand->decrRef();
11585           if(!isColinear)
11586               break;
11587         }
11588       //push [posBaseElt,posEndElt) in newConnOfCell using e
11589       // 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!
11590       if(nbOfTurn==0)
11591         // at the begining of the connectivity (insert type)
11592         EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11593       else if((nbOfHit+nbOfTurn) != (nbs-1))
11594         // in the middle
11595         EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11596       if ((nbOfHit+nbOfTurn) == (nbs-1))
11597         // at the end (only quad points to deal with)
11598         EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
11599       posBaseElt=posEndElt;
11600       e->decrRef();
11601     }
11602   if(!middles.empty())
11603     newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
11604   return ret;
11605 }
11606
11607 /*!
11608  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
11609  *
11610  * \return  int - the number of new nodes created.
11611  * \sa MEDCouplingUMesh::split2DCells
11612  */
11613 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
11614 {
11615   checkCoherency();
11616   int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
11617   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
11618   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
11619   const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
11620   const int *midPtr(mid->begin()),*midIPtr(midI->begin());
11621   const double *oldCoordsPtr(getCoords()->begin());
11622   int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
11623   int prevPosOfCi(ciPtr[0]);
11624   for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
11625     {
11626       int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
11627       for(int j=0;j<sz;j++)
11628         { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
11629       *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
11630       for(int j=0;j<sz;j++)//loop over subedges of oldConn
11631         {
11632           int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
11633           if(sz2==0)
11634             {
11635               if(j<sz-1)
11636                 cPtr[1]=oldConn[prevPosOfCi+2+j];
11637               cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
11638               continue;
11639             }
11640           std::vector<INTERP_KERNEL::Node *> ns(3);
11641           ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
11642           ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
11643           ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
11644           MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
11645           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
11646             {
11647               cPtr[1]=subPtr[offset2+k];
11648               cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
11649             }
11650           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
11651           if(j!=sz-1)
11652             { cPtr[1]=tmpEnd; }
11653           cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
11654         }
11655       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
11656       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
11657     }
11658   if(c->end()!=cPtr)
11659     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
11660   _nodal_connec->decrRef();
11661   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
11662   addCoo->rearrange(2);
11663   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
11664   setCoords(coo);
11665   return addCoo->getNumberOfTuples();
11666 }
11667
11668 void MEDCouplingUMesh::ComputeAllTypesInternal(std::set<INTERP_KERNEL::NormalizedCellType>& types, const DataArrayInt *nodalConnec, const DataArrayInt *nodalConnecIndex)
11669 {
11670   if(nodalConnec && nodalConnecIndex)
11671     {
11672       types.clear();
11673       const int *conn(nodalConnec->getConstPointer()),*connIndex(nodalConnecIndex->getConstPointer());
11674       int nbOfElem(nodalConnecIndex->getNbOfElems()-1);
11675       if(nbOfElem>0)
11676         for(const int *pt=connIndex;pt!=connIndex+nbOfElem;pt++)
11677           types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
11678     }
11679 }
11680
11681 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
11682     _own_cell(true),_cell_id(-1),_nb_cell(0)
11683 {
11684   if(mesh)
11685     {
11686       mesh->incrRef();
11687       _nb_cell=mesh->getNumberOfCells();
11688     }
11689 }
11690
11691 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
11692 {
11693   if(_mesh)
11694     _mesh->decrRef();
11695   if(_own_cell)
11696     delete _cell;
11697 }
11698
11699 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
11700     _own_cell(false),_cell_id(bg-1),
11701     _nb_cell(end)
11702 {
11703   if(mesh)
11704     mesh->incrRef();
11705 }
11706
11707 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
11708 {
11709   _cell_id++;
11710   if(_cell_id<_nb_cell)
11711     {
11712       _cell->next();
11713       return _cell;
11714     }
11715   else
11716     return 0;
11717 }
11718
11719 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
11720 {
11721   if(_mesh)
11722     _mesh->incrRef();
11723 }
11724
11725 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
11726 {
11727   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
11728 }
11729
11730 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
11731 {
11732   if(_mesh)
11733     _mesh->decrRef();
11734 }
11735
11736 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
11737     _itc(itc),
11738     _bg(bg),_end(end)
11739 {
11740   if(_mesh)
11741     _mesh->incrRef();
11742 }
11743
11744 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
11745 {
11746   if(_mesh)
11747     _mesh->decrRef();
11748 }
11749
11750 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
11751 {
11752   return _type;
11753 }
11754
11755 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
11756 {
11757   return _end-_bg;
11758 }
11759
11760 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
11761 {
11762   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
11763 }
11764
11765 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
11766 {
11767   if(mesh)
11768     {
11769       mesh->incrRef();
11770       _nb_cell=mesh->getNumberOfCells();
11771     }
11772 }
11773
11774 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
11775 {
11776   if(_mesh)
11777     _mesh->decrRef();
11778   delete _cell;
11779 }
11780
11781 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
11782 {
11783   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
11784   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
11785   if(_cell_id<_nb_cell)
11786     {
11787       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
11788       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
11789       int startId=_cell_id;
11790       _cell_id+=nbOfElems;
11791       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
11792     }
11793   else
11794     return 0;
11795 }
11796
11797 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
11798 {
11799   if(mesh)
11800     {
11801       _conn=mesh->getNodalConnectivity()->getPointer();
11802       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
11803     }
11804 }
11805
11806 void MEDCouplingUMeshCell::next()
11807 {
11808   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11809     {
11810       _conn+=_conn_lgth;
11811       _conn_indx++;
11812     }
11813   _conn_lgth=_conn_indx[1]-_conn_indx[0];
11814 }
11815
11816 std::string MEDCouplingUMeshCell::repr() const
11817 {
11818   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11819     {
11820       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
11821       oss << " : ";
11822       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
11823       return oss.str();
11824     }
11825   else
11826     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
11827 }
11828
11829 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
11830 {
11831   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11832     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
11833   else
11834     return INTERP_KERNEL::NORM_ERROR;
11835 }
11836
11837 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
11838 {
11839   lgth=_conn_lgth;
11840   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
11841     return _conn;
11842   else
11843     return 0;
11844 }