Salome HOME
caadbd866a3234d720f5aa0cb9831c74ee0fe7ae
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2013  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.
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 "MEDCouplingMemArray.txx"
23 #include "MEDCouplingFieldDouble.hxx"
24 #include "CellModel.hxx"
25 #include "VolSurfUser.txx"
26 #include "InterpolationUtils.hxx"
27 #include "PointLocatorAlgos.txx"
28 #include "BBTree.txx"
29 #include "SplitterTetra.hxx"
30 #include "DirectedBoundingBox.hxx"
31 #include "InterpKernelMeshQuality.hxx"
32 #include "InterpKernelCellSimplify.hxx"
33 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
34 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
35 #include "InterpKernelAutoPtr.hxx"
36 #include "InterpKernelGeo2DNode.hxx"
37 #include "InterpKernelGeo2DEdgeLin.hxx"
38 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
39 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
40
41 #include <sstream>
42 #include <fstream>
43 #include <numeric>
44 #include <cstring>
45 #include <limits>
46 #include <list>
47
48 using namespace ParaMEDMEM;
49
50 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
51
52 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 };
53
54 MEDCouplingUMesh *MEDCouplingUMesh::New()
55 {
56   return new MEDCouplingUMesh;
57 }
58
59 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
60 {
61   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
62   ret->setName(meshName);
63   ret->setMeshDimension(meshDim);
64   return ret;
65 }
66
67 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
68 {
69   return clone(true);
70 }
71
72 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
73 {
74   return new MEDCouplingUMesh(*this,recDeepCpy);
75 }
76
77 std::size_t MEDCouplingUMesh::getHeapMemorySize() const
78 {
79   std::size_t ret=0;
80   if(_nodal_connec)
81     ret+=_nodal_connec->getHeapMemorySize();
82   if(_nodal_connec_index)
83     ret+=_nodal_connec_index->getHeapMemorySize();
84   return MEDCouplingPointSet::getHeapMemorySize()+ret;
85 }
86
87 void MEDCouplingUMesh::updateTime() const
88 {
89   MEDCouplingPointSet::updateTime();
90   if(_nodal_connec)
91     {
92       updateTimeWith(*_nodal_connec);
93     }
94   if(_nodal_connec_index)
95     {
96       updateTimeWith(*_nodal_connec_index);
97     }
98 }
99
100 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
101 {
102 }
103
104 /*!
105  * This method checks that this is correctly designed. For example le coordinates are set, nodal connectivity.
106  * When this method returns without throwing any exception, 'this' is expected to be writable, exchangeable and to be 
107  * available for most of algorithm. When a mesh has been constructed from scratch it is a good habits to call this method to check
108  * that all is in order in 'this'.
109  */
110 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
111 {
112   if(_mesh_dim<-1)
113    throw INTERP_KERNEL::Exception("No mesh dimension specified !");
114   if(_mesh_dim!=-1)
115     MEDCouplingPointSet::checkCoherency();
116   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
117     {
118       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
119         {
120           std::ostringstream message;
121           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
122           throw INTERP_KERNEL::Exception(message.str().c_str());
123         }
124     }
125   if(_nodal_connec)
126     {
127       if(_nodal_connec->getNumberOfComponents()!=1)
128         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
129       if(_nodal_connec->getInfoOnComponent(0)!="")
130         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
131     }
132   if(_nodal_connec_index)
133     {
134       if(_nodal_connec_index->getNumberOfComponents()!=1)
135         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
136       if(_nodal_connec_index->getInfoOnComponent(0)!="")
137         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
138     }
139 }
140
141 /*!
142  * This method performs deeper checking in 'this' than MEDCouplingUMesh::checkCoherency does.
143  * So this method is more time-consuming. This method checks that nodal connectivity points to valid node ids.
144  * No geometrical aspects are checked here. These aspects are done in MEDCouplingUMesh::checkCoherency2.
145  */
146 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
147 {
148   checkCoherency();
149   if(_mesh_dim==-1)
150     return ;
151   int meshDim=getMeshDimension();
152   int nbOfNodes=getNumberOfNodes();
153   int nbOfCells=getNumberOfCells();
154   const int *ptr=_nodal_connec->getConstPointer();
155   const int *ptrI=_nodal_connec_index->getConstPointer();
156   for(int i=0;i<nbOfCells;i++)
157     {
158       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
159       if((int)cm.getDimension()!=meshDim)
160         {
161           std::ostringstream oss;
162           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
163           throw INTERP_KERNEL::Exception(oss.str().c_str());
164         }
165       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
166       if(!cm.isDynamic())
167         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
168           {
169             std::ostringstream oss;
170             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
171             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
172             throw INTERP_KERNEL::Exception(oss.str().c_str());
173           }
174       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
175         {
176           int nodeId=*w;
177           if(nodeId>=0)
178             {
179               if(nodeId>=nbOfNodes)
180                 {
181                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
182                   throw INTERP_KERNEL::Exception(oss.str().c_str());
183                 }
184             }
185           else if(nodeId<-1)
186             {
187               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
188               throw INTERP_KERNEL::Exception(oss.str().c_str());
189             }
190           else
191             {
192               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
193                 {
194                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
195                   throw INTERP_KERNEL::Exception(oss.str().c_str());
196                 }
197             }
198         }
199     }
200 }
201
202 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
203 {
204   checkCoherency1(eps);
205 }
206
207 void MEDCouplingUMesh::setMeshDimension(int meshDim)
208 {
209   if(meshDim<-1 || meshDim>3)
210     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
211   _mesh_dim=meshDim;
212   declareAsNew();
213 }
214
215 void MEDCouplingUMesh::allocateCells(int nbOfCells)
216 {
217   if(_nodal_connec_index)
218     {
219       _nodal_connec_index->decrRef();
220     }
221   if(_nodal_connec)
222     {
223       _nodal_connec->decrRef();
224     }
225   _nodal_connec_index=DataArrayInt::New();
226   _nodal_connec_index->reserve(nbOfCells+1);
227   _nodal_connec_index->pushBackSilent(0);
228   _nodal_connec=DataArrayInt::New();
229   _nodal_connec->reserve(2*nbOfCells);
230   _types.clear();
231   declareAsNew();
232 }
233
234 /*!
235  * Appends a cell in connectivity array.
236  * @param type type of cell to add.
237  * @param size number of nodes constituting this cell.
238  * @param nodalConnOfCell the connectivity of the cell to add.
239  */
240 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
241 {
242   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
243   if(_nodal_connec_index==0)
244     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
245   if((int)cm.getDimension()==_mesh_dim)
246     {
247       if(!cm.isDynamic())
248         if(size!=(int)cm.getNumberOfNodes())
249           {
250             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
251             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
252             throw INTERP_KERNEL::Exception(oss.str().c_str());
253           }
254       int idx=_nodal_connec_index->back();
255       int val=idx+size+1;
256       _nodal_connec_index->pushBackSilent(val);
257       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
258       _types.insert(type);
259     }
260   else
261     {
262       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
263       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
264       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
265       throw INTERP_KERNEL::Exception(oss.str().c_str());
266     }
267 }
268
269 /*!
270  * Method to be called to cloture the insertion of cells using this->insertNextCell.
271  */
272 void MEDCouplingUMesh::finishInsertingCells()
273 {
274   _nodal_connec->pack();
275   _nodal_connec_index->pack();
276   _nodal_connec->declareAsNew();
277   _nodal_connec_index->declareAsNew();
278   updateTime();
279 }
280
281 /*!
282  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
283  * Useful for python users.
284  */
285 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
286 {
287   return new MEDCouplingUMeshCellIterator(this);
288 }
289
290 /*!
291  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
292  * If 'this' is not so that that cells are grouped by geo types this method will throw an exception.
293  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
294  * Useful for python users.
295  */
296 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
297 {
298   if(!checkConsecutiveCellTypes())
299     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
300   return new MEDCouplingUMeshCellByTypeEntry(this);
301 }
302
303 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
304 {
305   return _types;
306 }
307
308 /*!
309  * This method is a method that compares 'this' and 'other'.
310  * This method compares \b all attributes, even names and component names.
311  */
312 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
313 {
314   if(!other)
315     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
316   std::ostringstream oss; oss.precision(15);
317   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
318   if(!otherC)
319     {
320       reason="mesh given in input is not castable in MEDCouplingUMesh !";
321       return false;
322     }
323   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
324     return false;
325   if(_mesh_dim!=otherC->_mesh_dim)
326     {
327       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
328       reason=oss.str();
329       return false;
330     }
331   if(_types!=otherC->_types)
332     {
333       oss << "umesh geometric type mismatch :\nThis geometric types are :";
334       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
335         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
336       oss << "\nOther geometric types are :";
337       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
338         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
339       reason=oss.str();
340       return false;
341     }
342   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
343     if(_nodal_connec==0 || otherC->_nodal_connec==0)
344       {
345         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
346         return false;
347       }
348   if(_nodal_connec!=otherC->_nodal_connec)
349     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
350       {
351         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
352         return false;
353       }
354   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
355     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
356       {
357         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
358         return false;
359       }
360   if(_nodal_connec_index!=otherC->_nodal_connec_index)
361     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
362       {
363         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
364         return false;
365       }
366   return true;
367 }
368
369 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
370 {
371   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
372   if(!otherC)
373     return false;
374   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
375     return false;
376   if(_mesh_dim!=otherC->_mesh_dim)
377     return false;
378   if(_types!=otherC->_types)
379     return false;
380   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
381     if(_nodal_connec==0 || otherC->_nodal_connec==0)
382       return false;
383   if(_nodal_connec!=otherC->_nodal_connec)
384     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
385       return false;
386   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
387     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
388       return false;
389   if(_nodal_connec_index!=otherC->_nodal_connec_index)
390     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
391       return false;
392   return true;
393 }
394
395 /*!
396  * This method looks if 'this' and 'other' are geometrically equivalent that is to say if each cell in 'other' correspond to one cell and only one
397  * in 'this' is found regarding 'prec' parameter and 'cellCompPol' parameter.
398  * 
399  * In case of success cellCor and nodeCor are informed both. 
400  * @param cellCompPol values are described in MEDCouplingUMesh::zipConnectivityTraducer method.
401  * @param cellCor output array giving the correspondance of cells from 'other' to 'this'.
402  * @param nodeCor output array giving the correspondance of nodes from 'other' to 'this'.
403  */
404 void MEDCouplingUMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
405                                             DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const throw(INTERP_KERNEL::Exception)
406 {
407   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
408   if(!otherC)
409     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Two meshes are not not unstructured !");
410   MEDCouplingMesh::checkFastEquivalWith(other,prec);
411   if(_types!=otherC->_types)
412     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Types are not equal !");
413   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshes(this,otherC);
414   bool areNodesMerged;
415   int newNbOfNodes;
416   int oldNbOfNodes=getNumberOfNodes();
417   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->buildPermArrayForMergeNode(prec,oldNbOfNodes,areNodesMerged,newNbOfNodes);
418   //mergeNodes
419   if(!areNodesMerged)
420     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : Nodes are incompatible ! ");
421   const int *pt=std::find_if(da->getConstPointer()+oldNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),oldNbOfNodes-1));
422   if(pt!=da->getConstPointer()+da->getNbOfElems())
423     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some nodes in other are not in this !");
424   m->renumberNodes(da->getConstPointer(),newNbOfNodes);
425   //
426   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodeCor2=da->substr(oldNbOfNodes);
427   da=m->mergeNodes(prec,areNodesMerged,newNbOfNodes);
428   
429   //
430   da=m->zipConnectivityTraducer(cellCompPol);
431   int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
432   pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
433   if(pt!=da->getConstPointer()+da->getNbOfElems())
434     throw INTERP_KERNEL::Exception("checkDeepEquivalWith : some cells in other are not in this !");
435   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
436   nodeCor=nodeCor2->isIdentity()?0:nodeCor2.retn();
437   cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
438 }
439
440 /*!
441  * This method looks if 'this' and 'other' are geometrically equivalent that is to say if each cell in 'other' correspond to one cell and only one
442  * in 'this' is found regarding 'prec' parameter and 'cellCompPol' parameter. The difference with MEDCouplingUMesh::checkDeepEquivalWith method is that
443  * coordinates of 'this' and 'other' are expected to be the same. If not an exception will be thrown.
444  * This method is close to MEDCouplingUMesh::areCellsIncludedIn except that this method throws exception !
445  * 
446  * In case of success cellCor are informed both. 
447  * @param cellCompPol values are described in MEDCouplingUMesh::zipConnectivityTraducer method.
448  * @param cellCor output array giving the correspondance of cells from 'other' to 'this'.
449  */
450 void MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
451                                                        DataArrayInt *&cellCor) const throw(INTERP_KERNEL::Exception)
452 {
453   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
454   if(!otherC)
455     throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Two meshes are not not unstructured !");
456   MEDCouplingMesh::checkFastEquivalWith(other,prec);
457   if(_types!=otherC->_types)
458     throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : Types are not equal !");
459   if(_coords!=otherC->_coords)
460     throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : meshes do not share the same coordinates ! Use tryToShareSameCoordinates or call checkDeepEquivalWith !");
461   std::vector<const MEDCouplingUMesh *> ms(2);
462   ms[0]=this;
463   ms[1]=otherC;
464   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=MergeUMeshesOnSameCoords(ms);
465   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=m->zipConnectivityTraducer(cellCompPol);
466   int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+getNumberOfCells());
467   const int *pt=std::find_if(da->getConstPointer()+getNumberOfCells(),da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
468   if(pt!=da->getConstPointer()+da->getNbOfElems())
469     {
470       throw INTERP_KERNEL::Exception("checkDeepEquivalOnSameNodesWith : some cells in other are not in this !");
471     }
472   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellCor2=da->selectByTupleId2(getNumberOfCells(),da->getNbOfElems(),1);
473   cellCor=cellCor2->isIdentity()?0:cellCor2.retn();
474 }
475
476 /*!
477  * This method checks fastly that 'this' and 'other' are equal. 
478  */
479 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
480 {
481   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
482   if(!otherC)
483     throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not not unstructured !");
484   MEDCouplingPointSet::checkFastEquivalWith(other,prec);
485   int nbOfCells=getNumberOfCells();
486   if(nbOfCells<1)
487     return ;
488   bool status=true;
489   status&=areCellsFrom2MeshEqual(otherC,0,prec);
490   status&=areCellsFrom2MeshEqual(otherC,nbOfCells/2,prec);
491   status&=areCellsFrom2MeshEqual(otherC,nbOfCells-1,prec);
492   if(!status)
493     throw INTERP_KERNEL::Exception("checkFastEquivalWith : Two meshes are not equal because on 3 test cells some difference have been detected !");
494 }
495
496 /*!
497  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
498  * For speed reasons no check of this will be done.
499  */
500 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
501 {
502   checkFullyDefined();
503   int nbOfNodes=getNumberOfNodes();
504   int *revNodalIndxPtr=new int[nbOfNodes+1];
505   revNodalIndx->useArray(revNodalIndxPtr,true,CPP_DEALLOC,nbOfNodes+1,1);
506   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
507   const int *conn=_nodal_connec->getConstPointer();
508   const int *connIndex=_nodal_connec_index->getConstPointer();
509   int nbOfCells=getNumberOfCells();
510   int nbOfEltsInRevNodal=0;
511   for(int eltId=0;eltId<nbOfCells;eltId++)
512     {
513       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
514       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
515       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
516         if(*iter>=0)//for polyhedrons
517           {
518             nbOfEltsInRevNodal++;
519             revNodalIndxPtr[(*iter)+1]++;
520           }
521     }
522   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
523   int *revNodalPtr=new int[nbOfEltsInRevNodal];
524   revNodal->useArray(revNodalPtr,true,CPP_DEALLOC,nbOfEltsInRevNodal,1);
525   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
526   for(int eltId=0;eltId<nbOfCells;eltId++)
527     {
528       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
529       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
530       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
531         if(*iter>=0)//for polyhedrons
532           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
533     }
534 }
535
536 /// @cond INTERNAL
537
538 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
539 {
540   return id;
541 }
542
543 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
544 {
545   if(!compute)
546     return id+1;
547   else
548     {
549       if(cm.getOrientationStatus(nb,conn1,conn2))
550         return id+1;
551       else
552         return -(id+1);
553     }
554 }
555
556 class MinusOneSonsGenerator
557 {
558 public:
559   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
560   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
561   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
562   static const int DELTA=1;
563 private:
564   const INTERP_KERNEL::CellModel& _cm;
565 };
566
567 class MinusOneSonsGeneratorBiQuadratic
568 {
569 public:
570   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
571   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
572   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
573   static const int DELTA=1;
574 private:
575   const INTERP_KERNEL::CellModel& _cm;
576 };
577
578 class MinusTwoSonsGenerator
579 {
580 public:
581   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
582   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
583   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
584   static const int DELTA=2;
585 private:
586   const INTERP_KERNEL::CellModel& _cm;
587 };
588
589 /// @endcond
590
591 /*!
592  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
593  * For speed reasons no check of this will be done.
594  * Given 'this' with spacedim equal to s and meshdim equal to p, this method returns a new allocated mesh
595  * lying on the same coordinates than 'this' and having a meshdim equal to p-1.
596  * The algorithm to compute this p-1 mesh is the following :
597  * For each cell in 'this' it splits into p-1 elements.
598  *   If this p-1 element does not already exists it is appended to the returned mesh
599  *   If this p-1 element already exists, it is not appended.
600  * This method returns or 4 arrays plus the returned mesh.
601  * 'desc' and 'descIndx' are the descending connectivity. These 2 arrays tell for each cell in 'this', to wich p-1 dimension cell in returned mesh it refers.
602  * For a cell with a cellid c in 'this' it is constituted of cells in [desc+descIndx[c],desc+descIndex[c+1])
603  *
604  * Reversely 'revDesc' and 'revDescIndx' are the reverse descending connectivity. These 2 arrays tell for each cell in returned mesh, to wich cell in 'this' it refers.
605  * For a cell with a cellid d in returned p-1 mesh it is shared by the following cells in 'this' [revDesc+revDescIndx[d],revDesc+revDescIndx[d+1])
606  *
607  * \warning This method returns a mesh whose geometric type order in are \b not sorted.
608  * In view of the MED file writing, a renumbering of cells in returned mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
609  */
610 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
611 {
612   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
613 }
614
615 /*!
616  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
617  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
618  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
619  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
620  * \sa MEDCouplingUMesh::buildDescendingConnectivity
621  */
622 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
623 {
624   checkFullyDefined();
625   if(getMeshDimension()!=3)
626     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
627   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
628 }
629
630 /*!
631  * WARNING this method do the assumption that connectivity lies on the coordinates set.
632  * For speed reasons no check of this will be done.
633  * This method differs from MEDCouplingUMesh::buildDescendingConnectivity method in that 'desc' is in different format.
634  * This method is more precise because it returns in descending connectivity giving the direction. If value is positive the n-1 dim element is taken in the same direction,
635  * if it is in the opposite direction it is retrieved negative. So the problem is for elemt #0 in C convention. That's why this method is the only one that retrieves 
636  * an array in relative "FORTRAN" mode.
637  *
638  * \warning This method returns a mesh whose geometric type order in are \b not sorted.
639  * In view of the MED file writing, a renumbering of cells in returned mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
640  */
641 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
642 {
643   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
644 }
645
646 /*!
647  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
648  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
649  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
650  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
651  *
652  * \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
653  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
654  * \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.
655  */
656 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
657 {
658   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
659   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
660   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
661   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
662   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
663   meshDM1=0;
664   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
665 }
666
667 /*!
668  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
669  * 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,
670  * excluding a set of meshdim-1 cells in input descending connectivity.
671  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
672  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
673  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
674  *
675  * \param [in] desc descending connectivity array.
676  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
677  * \param [in] revDesc reverse descending connectivity array.
678  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
679  * \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
680  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
681  * \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.
682  */
683 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
684                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
685 {
686   if(!desc || !descIndx || !revDesc || !revDescIndx)
687     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
688   const int *descPtr=desc->getConstPointer();
689   const int *descIPtr=descIndx->getConstPointer();
690   const int *revDescPtr=revDesc->getConstPointer();
691   const int *revDescIPtr=revDescIndx->getConstPointer();
692   //
693   int nbCells=descIndx->getNumberOfTuples()-1;
694   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
695   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
696   int *out1Ptr=out1->getPointer();
697   *out1Ptr++=0;
698   out0->reserve(desc->getNumberOfTuples());
699   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
700     {
701       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
702         {
703           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
704           s.erase(i);
705           out0->insertAtTheEnd(s.begin(),s.end());
706         }
707       *out1Ptr=out0->getNumberOfTuples();
708     }
709   neighbors=out0.retn();
710   neighborsIndx=out1.retn();
711 }
712
713 /// @cond INTERNAL
714
715 /*!
716  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
717  * For speed reasons no check of this will be done.
718  */
719 template<class SonsGenerator>
720 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
721 {
722   if(!desc || !descIndx || !revDesc || !revDescIndx)
723     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
724   checkConnectivityFullyDefined();
725   int nbOfCells=getNumberOfCells();
726   int nbOfNodes=getNumberOfNodes();
727   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
728   int *revNodalIndxPtr=revNodalIndx->getPointer();
729   const int *conn=_nodal_connec->getConstPointer();
730   const int *connIndex=_nodal_connec_index->getConstPointer();
731   std::string name="Mesh constituent of "; name+=getName();
732   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
733   ret->setCoords(getCoords());
734   ret->allocateCells(2*nbOfCells);
735   descIndx->alloc(nbOfCells+1,1);
736   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
737   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
738   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
739     {
740       int pos=connIndex[eltId];
741       int posP1=connIndex[eltId+1];
742       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
743       SonsGenerator sg(cm);
744       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
745       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
746       for(unsigned i=0;i<nbOfSons;i++)
747         {
748           INTERP_KERNEL::NormalizedCellType cmsId;
749           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
750           for(unsigned k=0;k<nbOfNodesSon;k++)
751             if(tmp[k]>=0)
752               revNodalIndxPtr[tmp[k]+1]++;
753           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
754           revDesc2->pushBackSilent(eltId);
755         }
756       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
757     }
758   int nbOfCellsM1=ret->getNumberOfCells();
759   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
761   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
762   int *revNodalPtr=revNodal->getPointer();
763   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
764   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
765   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
766     {
767       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
768       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
769       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
770         if(*iter>=0)//for polyhedrons
771           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
772     }
773   //
774   DataArrayInt *commonCells=0,*commonCellsI=0;
775   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
776   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
777   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
778   int newNbOfCellsM1=-1;
779   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
780                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
781   std::vector<bool> isImpacted(nbOfCellsM1,false);
782   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
783     for(int work2=work[0];work2!=work[1];work2++)
784       isImpacted[commonCellsPtr[work2]]=true;
785   const int *o2nM1Ptr=o2nM1->getConstPointer();
786   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
787   const int *n2oM1Ptr=n2oM1->getConstPointer();
788   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
789   ret2->copyTinyInfoFrom(this);
790   desc->alloc(descIndx->back(),1);
791   int *descPtr=desc->getPointer();
792   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
793   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
794     {
795       if(!isImpacted[i])
796         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
797       else
798         {
799           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
800             {
801               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
802               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
803             }
804           else
805             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
806         }
807     }
808   revDesc->reserve(newNbOfCellsM1);
809   revDescIndx->alloc(newNbOfCellsM1+1,1);
810   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
811   const int *revDesc2Ptr=revDesc2->getConstPointer();
812   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
813     {
814       int oldCellIdM1=n2oM1Ptr[i];
815       if(!isImpacted[oldCellIdM1])
816         {
817           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
818           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
819         }
820       else
821         {
822           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
823             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
824           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
825           commonCellsIPtr++;
826         }
827     }
828   //
829   return ret2.retn();
830 }
831
832 struct MEDCouplingAccVisit
833 {
834   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
835   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
836   int _new_nb_of_nodes;
837 };
838
839 /// @endcond
840
841
842 /*!
843  * This method convert cell with ids in ['cellIdsToConvertBg','cellIdsToConvertEnd') into 'this' into dynamic types without changing geometry.
844  * That is to say if 'this' is a 2D, mesh after the invocation of this method it will contain only polygons.
845  * If 'this' is a 3D mesh after the invocation of this method it will contain only polyhedra.
846  * If mesh dimension is not in [2,3] an exception is thrown.
847  * Of course pay attention that the resulting mesh is slower than previous one.
848  * If in ['cellIdsToConvertBg','cellIdsToConvertEnd') there is a cell id not in [0,'this->getNumberOfCells()') an exception will be thrown.
849  * In this case if meshDim==2 the mesh is still valid and only cells treated before throw will be converted into polygon.
850  * If mesh==3, after throw the mesh is \b unconsistent !
851  * This method is above all designed to test more extensively algorithms able to deal with polygons/polyhedra.
852  * 
853  * \warning This method modifies can modify significantly the geometric type order in \a this.
854  * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
855  */
856 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
857 {
858   checkFullyDefined();
859   int dim=getMeshDimension();
860   if(dim<2 || dim>3)
861     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
862   int nbOfCells=getNumberOfCells();
863   if(dim==2)
864     {
865       const int *connIndex=_nodal_connec_index->getConstPointer();
866       int *conn=_nodal_connec->getPointer();
867       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
868         {
869           if(*iter>=0 && *iter<nbOfCells)
870             {
871               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
872               if(!cm.isDynamic())
873                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
874               else
875                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
876             }
877           else
878             {
879               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
880               oss << " in range [0," << nbOfCells << ") !";
881               throw INTERP_KERNEL::Exception(oss.str().c_str());
882             }
883         }
884     }
885   else
886     {
887       int *connIndex=_nodal_connec_index->getPointer();
888       int connIndexLgth=_nodal_connec_index->getNbOfElems();
889       const int *connOld=_nodal_connec->getConstPointer();
890       int connOldLgth=_nodal_connec->getNbOfElems();
891       std::vector<int> connNew(connOld,connOld+connOldLgth);
892       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
893         {
894           if(*iter>=0 && *iter<nbOfCells)
895             {
896               int pos=connIndex[*iter];
897               int posP1=connIndex[(*iter)+1];
898               int lgthOld=posP1-pos-1;
899               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
900               connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
901               unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
902               int *tmp=new int[nbOfFaces*lgthOld];
903               int *work=tmp;
904               for(int j=0;j<(int)nbOfFaces;j++)
905                 {
906                   INTERP_KERNEL::NormalizedCellType type;
907                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
908                   work+=offset;
909                   *work++=-1;
910                 }
911               std::size_t newLgth=std::distance(tmp,work)-1;
912               std::size_t delta=newLgth-lgthOld;
913               std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
914               connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
915               std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
916               delete [] tmp;
917             }
918           else
919             {
920               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
921               oss << " in range [0," << nbOfCells << ") !";
922               throw INTERP_KERNEL::Exception(oss.str().c_str());
923             }
924         }
925       _nodal_connec->alloc((int)connNew.size(),1);
926       int *newConnPtr=_nodal_connec->getPointer();
927       std::copy(connNew.begin(),connNew.end(),newConnPtr);
928     }
929   computeTypes();
930 }
931
932 /*!
933  * This method converts all cells into poly type if possible.
934  * This method is purely for userfriendliness.
935  * As this method can be costly in Memory, no optimization is done to avoid construction of useless vector.
936  */
937 void MEDCouplingUMesh::convertAllToPoly()
938 {
939   int nbOfCells=getNumberOfCells();
940   std::vector<int> cellIds(nbOfCells);
941   for(int i=0;i<nbOfCells;i++)
942     cellIds[i]=i;
943   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
944 }
945
946 /*!
947  * This method expects that 'this' has a spacedim equal to 3 and a mesh dimension equal to 3 too, if not an exception will be thrown.
948  * This method work only on cells with type NORM_POLYHED, all other cells with different type, are remains unchanged.
949  * For such polyhedra, they are expected to have only 1 face (containing 2 faces in opposition), having 2*n number of nodes (n nodes on
950  * each 2 faces hidden in the single face of polyhedron).
951  * The first face is expected to be right oriented because all faces of this polyhedron will be deduced.
952  * When called 'this' is an invalid mesh on MED sense. This method will correct that for polyhedra.
953  * In case of presence of polyhedron that has not the extruded aspect (2 faces with the same number of nodes) an exception is thrown and 'this'
954  * remains unchanged.
955  * This method is useful only for users that wants to build extruded unstructured mesh.
956  * This method is a convenient one that avoids boring polyhedra setting during insertNextCell process.
957  * In case of success, 'this' has be corrected contains the same number of cells and is valid in MED sense.
958  */
959 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
960 {
961   checkFullyDefined();
962   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
963     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
964   int nbOfCells=getNumberOfCells();
965   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
966   newCi->alloc(nbOfCells+1,1);
967   int *newci=newCi->getPointer();
968   const int *ci=_nodal_connec_index->getConstPointer();
969   const int *c=_nodal_connec->getConstPointer();
970   newci[0]=0;
971   for(int i=0;i<nbOfCells;i++)
972     {
973       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
974       if(type==INTERP_KERNEL::NORM_POLYHED)
975         {
976           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
977             {
978               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
979               throw INTERP_KERNEL::Exception(oss.str().c_str());
980             }
981           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
982           if(n2%2!=0)
983             {
984               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 !";
985               throw INTERP_KERNEL::Exception(oss.str().c_str());
986             }
987           int n1=(int)(n2/2);
988           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)
989         }
990       else
991         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
992     }
993   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
994   newC->alloc(newci[nbOfCells],1);
995   int *newc=newC->getPointer();
996   for(int i=0;i<nbOfCells;i++)
997     {
998       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
999       if(type==INTERP_KERNEL::NORM_POLYHED)
1000         {
1001           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1002           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1003           *newc++=-1;
1004           for(std::size_t j=0;j<n1;j++)
1005             {
1006               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1007               newc[n1+5*j]=-1;
1008               newc[n1+5*j+1]=c[ci[i]+1+j];
1009               newc[n1+5*j+2]=c[ci[i]+1+(j+1)%n1];
1010               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1011               newc[n1+5*j+4]=c[ci[i]+1+j+n1];
1012             }
1013           newc+=n1*6;
1014         }
1015       else
1016         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1017     }
1018   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1019   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1020 }
1021
1022 /*!
1023  * This method is the opposite of ParaMEDMEM::MEDCouplingUMesh::convertToPolyTypes method.
1024  * The aim is to take all polygons or polyhedrons cell and to try to traduce them into classical cells.
1025  *
1026  *  \return If true at least one cell has been unpolyzed.
1027             \n If false has been returned the nodal connectivity of \a this has **not** been altered and \a this has remains unchanged.
1028  *
1029  * \warning This method modifies can modify significantly the geometric type order in \a this.
1030  * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1031  */
1032 bool MEDCouplingUMesh::unPolyze()
1033 {
1034   checkFullyDefined();
1035   int mdim=getMeshDimension();
1036   if(mdim<0)
1037     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1038   if(mdim<=1)
1039     return false;
1040   int nbOfCells=getNumberOfCells();
1041   if(nbOfCells<1)
1042     return false;
1043   int initMeshLgth=getMeshLength();
1044   int *conn=_nodal_connec->getPointer();
1045   int *index=_nodal_connec_index->getPointer();
1046   int posOfCurCell=0;
1047   int newPos=0;
1048   int lgthOfCurCell;
1049   bool ret=false;
1050   for(int i=0;i<nbOfCells;i++)
1051     {
1052       lgthOfCurCell=index[i+1]-posOfCurCell;
1053       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1054       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1055       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1056       int newLgth;
1057       if(cm.isDynamic())
1058         {
1059           switch(cm.getDimension())
1060             {
1061             case 2:
1062               {
1063                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1064                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1065                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1066                 break;
1067               }
1068             case 3:
1069               {
1070                 int nbOfFaces,lgthOfPolyhConn;
1071                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1072                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1073                 break;
1074               }
1075             case 1:
1076               {
1077                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1078                 break;
1079               }
1080             }
1081           ret=ret || (newType!=type);
1082           conn[newPos]=newType;
1083           newPos+=newLgth+1;
1084           posOfCurCell=index[i+1];
1085           index[i+1]=newPos;
1086         }
1087       else
1088         {
1089           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1090           newPos+=lgthOfCurCell;
1091           posOfCurCell+=lgthOfCurCell;
1092           index[i+1]=newPos;
1093         }
1094     }
1095   if(newPos!=initMeshLgth)
1096     _nodal_connec->reAlloc(newPos);
1097   if(ret)
1098     computeTypes();
1099   return ret;
1100 }
1101
1102 /*!
1103  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1104  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1105  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1106  *
1107  * \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 
1108  *             precision.
1109  */
1110 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1111 {
1112   checkFullyDefined();
1113   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1114     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1115   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1116   coords->recenterForMaxPrecision(eps);
1117   //
1118   int nbOfCells=getNumberOfCells();
1119   const int *conn=_nodal_connec->getConstPointer();
1120   const int *index=_nodal_connec_index->getConstPointer();
1121   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1122   connINew->alloc(nbOfCells+1,1);
1123   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1124   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1125   bool changed=false;
1126   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1127     {
1128       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1129         {
1130           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1131           changed=true;
1132         }
1133       else
1134         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1135       *connINewPtr=connNew->getNumberOfTuples();
1136     }
1137   if(changed)
1138     setConnectivity(connNew,connINew,false);
1139 }
1140
1141 /*!
1142  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1143  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1144  * the format of returned DataArrayInt instance.
1145  * 
1146  * @return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1147  * \sa MEDCouplingUMesh::getNodeIdsInUse
1148  */
1149 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1150 {
1151   checkConnectivityFullyDefined();
1152   int nbOfCells=getNumberOfCells();
1153   const int *connIndex=_nodal_connec_index->getConstPointer();
1154   const int *conn=_nodal_connec->getConstPointer();
1155   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1156   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1157   std::vector<bool> retS(maxElt,false);
1158   for(int i=0;i<nbOfCells;i++)
1159     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1160       if(conn[j]>=0)
1161         retS[conn[j]]=true;
1162   int sz=0;
1163   for(int i=0;i<maxElt;i++)
1164     if(retS[i])
1165       sz++;
1166   DataArrayInt *ret=DataArrayInt::New();
1167   ret->alloc(sz,1);
1168   int *retPtr=ret->getPointer();
1169   for(int i=0;i<maxElt;i++)
1170     if(retS[i])
1171       *retPtr++=i;
1172   return ret;
1173 }
1174
1175 /*!
1176  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1177  * \sa MEDCouplingUMesh::getNodeIdsInUse
1178  */
1179 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1180 {
1181   int nbOfNodes=(int)nodeIdsInUse.size();
1182   int nbOfCells=getNumberOfCells();
1183   const int *connIndex=_nodal_connec_index->getConstPointer();
1184   const int *conn=_nodal_connec->getConstPointer();
1185   for(int i=0;i<nbOfCells;i++)
1186     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1187       if(conn[j]>=0)
1188         {
1189           if(conn[j]<nbOfNodes)
1190             nodeIdsInUse[conn[j]]=true;
1191           else
1192             {
1193               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1194               throw INTERP_KERNEL::Exception(oss.str().c_str());
1195             }
1196         }
1197 }
1198
1199 /*!
1200  * Array returned is the correspondance in \b old \b to \b new format (that's why 'nbrOfNodesInUse' is returned too).
1201  * The returned array is newly created and should be dealt by the caller.
1202  * To retrieve the new to old format the user can use DataArrayInt::invertArrayO2N2N2O method.
1203  * The size of returned array is the number of nodes of 'this'.
1204  * -1 values in returned array means that the corresponding node never appear in any nodal connectivity of cells constituting 'this'.
1205  * @param [out] nbrOfNodesInUse out parameter that specifies how many of nodes in 'this' is really used in nodal connectivity.
1206  * @return a newly allocated DataArrayInt that tells for each nodeid in \b this if it is unused (-1) or used (the corresponding new id)
1207  * \throw if a cell contains in its nodal connectivity a node id >= nb of nodes an exception will be thrown.
1208  * \sa MEDCouplingUMesh::computeNodeIdsAlg
1209  */
1210 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1211 {
1212   nbrOfNodesInUse=-1;
1213   int nbOfNodes=getNumberOfNodes();
1214   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1215   ret->alloc(nbOfNodes,1);
1216   int *traducer=ret->getPointer();
1217   std::fill(traducer,traducer+nbOfNodes,-1);
1218   int nbOfCells=getNumberOfCells();
1219   const int *connIndex=_nodal_connec_index->getConstPointer();
1220   const int *conn=_nodal_connec->getConstPointer();
1221   for(int i=0;i<nbOfCells;i++)
1222     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1223       if(conn[j]>=0)
1224         {
1225           if(conn[j]<nbOfNodes)
1226             traducer[conn[j]]=1;
1227           else
1228             {
1229               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1230               throw INTERP_KERNEL::Exception(oss.str().c_str());
1231             }
1232         }
1233   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1234   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1235   return ret.retn();
1236 }
1237
1238 /*!
1239  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1240  * For each cell in \b this the number of nodes constituting cell is computed.
1241  * Excepted for poyhedrons, the result can be deduced by performing a deltaShiftIndex on the nodal connectivity index in \b this minus 1.
1242  * For polyhedrons, the face separation (-1) are excluded from the couting.
1243  * 
1244  * \return a newly allocated array
1245  */
1246 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1247 {
1248   checkConnectivityFullyDefined();
1249   int nbOfCells=getNumberOfCells();
1250   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1251   ret->alloc(nbOfCells,1);
1252   int *retPtr=ret->getPointer();
1253   const int *conn=getNodalConnectivity()->getConstPointer();
1254   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1255   for(int i=0;i<nbOfCells;i++,retPtr++)
1256     {
1257       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1258         *retPtr=connI[i+1]-connI[i]-1;
1259       else
1260         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1261     }
1262   return ret.retn();
1263 }
1264
1265 /*!
1266  * Array returned is the correspondance in \b old \b to \b new format. The returned array is newly created and should be dealt by the caller.
1267  * The maximum value stored in returned array is the number of nodes of 'this' minus 1 after call of this method.
1268  * The size of returned array is the number of nodes of the old (previous to the call of this method) number of nodes.
1269  * -1 values in returned array means that the corresponding old node is no more used.
1270  */
1271 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1272 {
1273   int newNbOfNodes=-1;
1274   DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1275   renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1276   return traducer;
1277 }
1278
1279 /*!
1280  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1281  * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1282  */
1283 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1284 {
1285   switch(compType)
1286     {
1287     case 0:
1288       return AreCellsEqual0(conn,connI,cell1,cell2);
1289     case 1:
1290       return AreCellsEqual1(conn,connI,cell1,cell2);
1291     case 2:
1292       return AreCellsEqual2(conn,connI,cell1,cell2);
1293     case 3:
1294       return AreCellsEqual3(conn,connI,cell1,cell2);
1295     case 7:
1296       return AreCellsEqual7(conn,connI,cell1,cell2);
1297     }
1298   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1299 }
1300
1301 /*!
1302  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 0.
1303  */
1304 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1305 {
1306   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1307     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1308   return 0;
1309 }
1310
1311 /*!
1312  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 1.
1313  */
1314 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1315 {
1316   int sz=connI[cell1+1]-connI[cell1];
1317   if(sz==connI[cell2+1]-connI[cell2])
1318     {
1319       if(conn[connI[cell1]]==conn[connI[cell2]])
1320         {
1321           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1322           unsigned dim=cm.getDimension();
1323           if(dim!=3)
1324             {
1325               if(dim!=1)
1326                 {
1327                   int sz1=2*(sz-1);
1328                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1329                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1330                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1331                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1332                   return work!=tmp+sz1?1:0;
1333                 }
1334               else
1335                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1336             }
1337           else
1338             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1339         }
1340     }
1341   return 0;
1342 }
1343
1344 /*!
1345  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 2.
1346  */
1347 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1348 {
1349   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1350     {
1351       if(conn[connI[cell1]]==conn[connI[cell2]])
1352         {
1353           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1354           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1355           return s1==s2?1:0;
1356         }
1357     }
1358   return 0;
1359 }
1360
1361 /*!
1362  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1363  */
1364 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1365 {
1366   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1367     {
1368       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1369       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1370       return s1==s2?1:0;
1371     }
1372   return 0;
1373 }
1374
1375 /*!
1376  * This method is the last step of the MEDCouplingUMesh::zipConnectivityTraducer with policy 7.
1377  */
1378 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1379 {
1380   int sz=connI[cell1+1]-connI[cell1];
1381   if(sz==connI[cell2+1]-connI[cell2])
1382     {
1383       if(conn[connI[cell1]]==conn[connI[cell2]])
1384         {
1385           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1386           unsigned dim=cm.getDimension();
1387           if(dim!=3)
1388             {
1389               if(dim!=1)
1390                 {
1391                   int sz1=2*(sz-1);
1392                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1393                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1394                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1395                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1396                   if(work!=tmp+sz1)
1397                     return 1;
1398                   else
1399                     {
1400                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1401                       std::reverse_iterator<int *> it2((int *)tmp);
1402                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1403                         return 2;
1404                       else
1405                         return 0;
1406                     }
1407                   
1408                   return work!=tmp+sz1?1:0;
1409                 }
1410               else
1411                 {//case of SEG2 and SEG3
1412                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1413                     return 1;
1414                   if(!cm.isQuadratic())
1415                     {
1416                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1417                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1418                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1419                         return 2;
1420                       return 0;
1421                     }
1422                   else
1423                     {
1424                       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])
1425                         return 2;
1426                       return 0;
1427                     }
1428                 }
1429             }
1430           else
1431             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1432         }
1433     }
1434   return 0;
1435 }
1436
1437
1438 /*!
1439  * This method compares 2 cells coming from two unstructured meshes : 'this' and 'other'.
1440  * This method compares 2 cells having the same id 'cellId' in 'this' and 'other'.
1441  */
1442 bool MEDCouplingUMesh::areCellsFrom2MeshEqual(const MEDCouplingUMesh *other, int cellId, double prec) const
1443 {
1444   if(getTypeOfCell(cellId)!=other->getTypeOfCell(cellId))
1445     return false;
1446   std::vector<int> c1,c2;
1447   getNodeIdsOfCell(cellId,c1);
1448   other->getNodeIdsOfCell(cellId,c2);
1449   std::size_t sz=c1.size();
1450   if(sz!=c2.size())
1451     return false;
1452   for(std::size_t i=0;i<sz;i++)
1453     {
1454       std::vector<double> n1,n2;
1455       getCoordinatesOfNode(c1[0],n1);
1456       other->getCoordinatesOfNode(c2[0],n2);
1457       std::transform(n1.begin(),n1.end(),n2.begin(),n1.begin(),std::minus<double>());
1458       std::transform(n1.begin(),n1.end(),n1.begin(),std::ptr_fun<double,double>(fabs));
1459       if(*std::max_element(n1.begin(),n1.end())>prec)
1460         return false;
1461     }
1462   return true;
1463 }
1464
1465 /*!
1466  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1467  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1468  * and result remains unchanged.
1469  * The semantic of 'compType' is specified in MEDCouplingUMesh::zipConnectivityTraducer method.
1470  * If in 'candidates' pool -1 value is considered as an empty value.
1471  * WARNING this method returns only ONE set of result !
1472  */
1473 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1474 {
1475   if(candidates.size()<1)
1476     return false;
1477   bool ret=false;
1478   std::vector<int>::const_iterator iter=candidates.begin();
1479   int start=(*iter++);
1480   for(;iter!=candidates.end();iter++)
1481     {
1482       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1483       if(status!=0)
1484         {
1485           if(!ret)
1486             {
1487               result->pushBackSilent(start);
1488               ret=true;
1489             }
1490           if(status==1)
1491             result->pushBackSilent(*iter);
1492           else
1493             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1494         }
1495     }
1496   return ret;
1497 }
1498
1499 /*!
1500  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1501  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1502  *
1503  * \param [in] compType input specifying the technique used to compare cells each other.
1504  *   - 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.
1505  *   - 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)
1506  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1507  *   - 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
1508  * can be used for users not sensitive to orientation of cell
1509  * \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.
1510  * \param [out] commonCells
1511  * \param [out] commonCellsI
1512  * \return the correspondance array old to new in a newly allocated array.
1513  * 
1514  */
1515 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1516 {
1517   checkConnectivityFullyDefined();
1518   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1519   getReverseNodalConnectivity(revNodal,revNodalI);
1520   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1521 }
1522
1523 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1524                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1525 {
1526   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1527   int nbOfCells=nodalI->getNumberOfTuples()-1;
1528   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1529   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1530   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1531   std::vector<bool> isFetched(nbOfCells,false);
1532   if(startCellId==0)
1533     {
1534       for(int i=0;i<nbOfCells;i++)
1535         {
1536           if(!isFetched[i])
1537             {
1538               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1539               std::vector<int> v,v2;
1540               if(connOfNode!=connPtr+connIPtr[i+1])
1541                 {
1542                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1543                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1544                   connOfNode++;
1545                 }
1546               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1547                 if(*connOfNode>=0)
1548                   {
1549                     v=v2;
1550                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1551                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1552                     v2.resize(std::distance(v2.begin(),it));
1553                   }
1554               if(v2.size()>1)
1555                 {
1556                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1557                     {
1558                       int pos=commonCellsI->back();
1559                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1560                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1561                         isFetched[*it]=true;
1562                     }
1563                 }
1564             }
1565         }
1566     }
1567   else
1568     {
1569       for(int i=startCellId;i<nbOfCells;i++)
1570         {
1571           if(!isFetched[i])
1572             {
1573               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1574               std::vector<int> v,v2;
1575               if(connOfNode!=connPtr+connIPtr[i+1])
1576                 {
1577                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1578                   connOfNode++;
1579                 }
1580               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1581                 if(*connOfNode>=0)
1582                   {
1583                     v=v2;
1584                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1585                     v2.resize(std::distance(v2.begin(),it));
1586                   }
1587               if(v2.size()>1)
1588                 {
1589                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1590                     {
1591                       int pos=commonCellsI->back();
1592                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1593                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1594                         isFetched[*it]=true;
1595                     }
1596                 }
1597             }
1598         }
1599     }
1600   commonCellsArr=commonCells.retn();
1601   commonCellsIArr=commonCellsI.retn();
1602 }
1603
1604 /*!
1605  * This method could potentially modify \a this. This method merges cells if there are cells equal in \a this. The comparison is specified by \a compType.
1606  * This method keeps the coordiantes of \a this.
1607  *
1608  * \param [in] compType input specifying the technique used to compare cells each other.
1609  *   - 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.
1610  *   - 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)
1611  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1612  *   - 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
1613  * can be used for users not sensitive to orientation of cell
1614  * \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
1615  * \return the correspondance array old to new in a newly allocated array.
1616  * 
1617  * \warning This method modifies can modify significantly the geometric type order in \a this.
1618  * In view of the MED file writing, a renumbering of cells in \a this (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1619  */
1620 DataArrayInt *MEDCouplingUMesh::zipConnectivityTraducer(int compType, int startCellId) throw(INTERP_KERNEL::Exception)
1621 {
1622   DataArrayInt *commonCells=0,*commonCellsI=0;
1623   findCommonCells(compType,startCellId,commonCells,commonCellsI);
1624   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1625   int newNbOfCells=-1;
1626   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(getNumberOfCells(),commonCells->begin(),commonCellsI->begin(),
1627                                                                                                           commonCellsI->end(),newNbOfCells);
1628   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2=ret->invertArrayO2N2N2O(newNbOfCells);
1629   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> self=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret2->begin(),ret2->end(),true));
1630   setConnectivity(self->getNodalConnectivity(),self->getNodalConnectivityIndex(),true);
1631   return ret.retn();
1632 }
1633
1634 /*!
1635  * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1636  * This method tries to determine if 'other' is fully included in 'this'. To compute that, this method works with connectivity as MEDCouplingUMesh::zipConnectivityTraducer method does. 
1637  * This method is close to MEDCouplingUMesh::checkDeepEquivalOnSameNodesWith or MEDCouplingMesh::checkGeoEquivalWith with policy 20,21,or 22.
1638  * The main difference is that this method is not expected to throw exception.
1639  * This method has two outputs :
1640  *
1641  * @param compType is the comparison type. The possible values of this parameter are described in ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer method
1642  * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1643  * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1644  */
1645 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1646 {
1647   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1648   int nbOfCells=getNumberOfCells();
1649   static const int possibleCompType[]={0,1,2};
1650   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1651     {
1652       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1653       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1654       oss << " !";
1655       throw INTERP_KERNEL::Exception(oss.str().c_str());
1656     }
1657   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1658   arr=o2n->substr(nbOfCells);
1659   arr->setName(other->getName());
1660   int tmp;
1661   if(other->getNumberOfCells()==0)
1662     return true;
1663   return arr->getMaxValue(tmp)<nbOfCells;
1664 }
1665
1666 /*!
1667  * This method makes the assumption that 'this' and 'other' share the same coords. If not an exception will be thrown !
1668  * This method tries to determine if \b other is fully included in \b this.
1669  * The main difference is that this method is not expected to throw exception.
1670  * This method has two outputs :
1671  *
1672  * @param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1673  * @return If 'other' is fully included in 'this 'true is returned. If not false is returned.
1674  */
1675 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1676 {
1677   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1678   DataArrayInt *commonCells=0,*commonCellsI=0;
1679   int thisNbCells=getNumberOfCells();
1680   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1681   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1682   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1683   int otherNbCells=other->getNumberOfCells();
1684   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1685   arr2->alloc(otherNbCells,1);
1686   arr2->fillWithZero();
1687   int *arr2Ptr=arr2->getPointer();
1688   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1689   for(int i=0;i<nbOfCommon;i++)
1690     {
1691       int start=commonCellsPtr[commonCellsIPtr[i]];
1692       if(start<thisNbCells)
1693         {
1694           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1695             {
1696               int sig=commonCellsPtr[j]>0?1:-1;
1697               int val=std::abs(commonCellsPtr[j])-1;
1698               if(val>=thisNbCells)
1699                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1700             }
1701         }
1702     }
1703   arr2->setName(other->getName());
1704   if(arr2->presenceOfValue(0))
1705     return false;
1706   arr=arr2.retn();
1707   return true;
1708 }
1709
1710 /*!
1711  * @param areNodesMerged if at least two nodes have been merged.
1712  * @return old to new node correspondance.
1713  */
1714 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1715 {
1716   DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1717   if(areNodesMerged)
1718     renumberNodes(ret->getConstPointer(),newNbOfNodes);
1719   return ret;
1720 }
1721
1722 /*!
1723  * Idem ParaMEDMEM::MEDCouplingUMesh::mergeNodes method except that the merged nodes are meld into the barycenter of them.
1724  */
1725 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
1726 {
1727   DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1728   if(areNodesMerged)
1729     renumberNodes2(ret->getConstPointer(),newNbOfNodes);
1730   return ret;
1731 }
1732
1733 /*!
1734  * This method tries to use 'other' coords and use it for 'this'. If no exception was thrown after the call of this method :
1735  * this->_coords==other->_coords. If an exception is thrown 'this' remains unchanged.
1736  * Contrary to MEDCouplingUMesh::tryToShareSameCoords method this method makes a deeper analyze of coordinates (and so more expensive) than simple equality.
1737  * Two nodes one in 'this' and other in 'other' are considered equal if the distance between the two is lower than epsilon.
1738  */
1739 void MEDCouplingUMesh::tryToShareSameCoordsPermute(const MEDCouplingPointSet& other, double epsilon) throw(INTERP_KERNEL::Exception)
1740 {
1741   const DataArrayDouble *coords=other.getCoords();
1742   if(!coords)
1743     throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in other !");
1744   if(!_coords)
1745     throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute : No coords specified in this whereas there is any in other !");
1746   int otherNbOfNodes=other.getNumberOfNodes();
1747   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=MergeNodesArray(&other,this);
1748   _coords->incrRef();
1749   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> oldCoords=_coords;
1750   setCoords(newCoords);
1751   bool areNodesMerged;
1752   int newNbOfNodes;
1753   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=buildPermArrayForMergeNode(epsilon,otherNbOfNodes,areNodesMerged,newNbOfNodes);
1754   if(!areNodesMerged)
1755     {
1756       setCoords(oldCoords);
1757       throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : no nodes are mergeable with specified given epsilon !");
1758     }
1759   int maxId=*std::max_element(da->getConstPointer(),da->getConstPointer()+otherNbOfNodes);
1760   const int *pt=std::find_if(da->getConstPointer()+otherNbOfNodes,da->getConstPointer()+da->getNbOfElems(),std::bind2nd(std::greater<int>(),maxId));
1761   if(pt!=da->getConstPointer()+da->getNbOfElems())
1762     {
1763       setCoords(oldCoords);
1764       throw INTERP_KERNEL::Exception("tryToShareSameCoordsPermute fails : some nodes in this are not in other !");
1765     }
1766   setCoords(oldCoords);
1767   renumberNodesInConn(da->getConstPointer()+otherNbOfNodes);
1768   setCoords(coords);
1769 }
1770
1771 /*!
1772  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1773  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1774  * cellIds is not given explicitely but by a range python like.
1775  * 
1776  * \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.
1777  * \return a newly allocated
1778  * 
1779  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1780  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1781  */
1782 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1783 {
1784   if(getMeshDimension()!=-1)
1785     {
1786       MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords2(start,end,step);
1787       if(!keepCoords)
1788         ret->zipCoords();
1789       return ret;
1790     }
1791   else
1792     {
1793       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1794       if(newNbOfCells!=1)
1795         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1796       if(start!=0)
1797         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1798       incrRef();
1799       return const_cast<MEDCouplingUMesh *>(this);
1800     }
1801 }
1802
1803 /*!
1804  * build a sub part of \b this. This sub part is defined by the cell ids contained in the array in [begin,end).
1805  * @param begin begin of array containing the cell ids to keep.
1806  * @param end end of array of cell ids to keep. \b WARNING end param is \b not included ! Idem STL standard definitions.
1807  * @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.
1808  * 
1809  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1810  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1811  */
1812 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1813 {
1814   if(getMeshDimension()!=-1)
1815     {
1816       MEDCouplingUMesh *ret=buildPartOfMySelfKeepCoords(begin,end);
1817       if(!keepCoords)
1818         ret->zipCoords();
1819       return ret;
1820     }
1821   else
1822     {
1823       if(end-begin!=1)
1824         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1825       if(begin[0]!=0)
1826         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1827       incrRef();
1828       return const_cast<MEDCouplingUMesh *>(this);
1829     }
1830 }
1831
1832 /*!
1833  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1834  *
1835  * 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.
1836  * Size of [\b cellIdsBg, \b cellIdsEnd) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1837  * The number of cells of \b this will remain the same with this method.
1838  *
1839  * \param [in] begin begin of cell ids (included) of cells in this to assign
1840  * \param [in] end end of cell ids (excluded) of cells in this to assign
1841  * \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).
1842  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1843  */
1844 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1845 {
1846   checkConnectivityFullyDefined();
1847   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1848   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1849     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1850   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1851     {
1852       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1853       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1854       throw INTERP_KERNEL::Exception(oss.str().c_str());
1855     }
1856   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1857   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1858     {
1859       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1860       throw INTERP_KERNEL::Exception(oss.str().c_str());
1861     }
1862   int nbOfCells=getNumberOfCells();
1863   bool easyAssign=true;
1864   const int *connI=_nodal_connec_index->getConstPointer();
1865   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1866   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1867     {
1868       if(*it>=0 && *it<nbOfCells)
1869         {
1870           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1871         }
1872       else
1873         {
1874           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1875           throw INTERP_KERNEL::Exception(oss.str().c_str());
1876         }
1877     }
1878   if(easyAssign)
1879     {
1880       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1881       computeTypes();
1882     }
1883   else
1884     {
1885       DataArrayInt *arrOut=0,*arrIOut=0;
1886       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1887                                                arrOut,arrIOut);
1888       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1889       setConnectivity(arrOut,arrIOut,true);
1890     }
1891 }
1892
1893 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1894 {
1895   checkConnectivityFullyDefined();
1896   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1897   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1898     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1899   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1900     {
1901       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1902       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1903       throw INTERP_KERNEL::Exception(oss.str().c_str());
1904     }
1905   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
1906   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1907     {
1908       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1909       throw INTERP_KERNEL::Exception(oss.str().c_str());
1910     }
1911   int nbOfCells=getNumberOfCells();
1912   bool easyAssign=true;
1913   const int *connI=_nodal_connec_index->getConstPointer();
1914   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1915   int it=start;
1916   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
1917     {
1918       if(it>=0 && it<nbOfCells)
1919         {
1920           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
1921         }
1922       else
1923         {
1924           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
1925           throw INTERP_KERNEL::Exception(oss.str().c_str());
1926         }
1927     }
1928   if(easyAssign)
1929     {
1930       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1931       computeTypes();
1932     }
1933   else
1934     {
1935       DataArrayInt *arrOut=0,*arrIOut=0;
1936       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1937                                                 arrOut,arrIOut);
1938       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1939       setConnectivity(arrOut,arrIOut,true);
1940     }
1941 }                      
1942
1943 DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
1944 {
1945   DataArrayInt *cellIdsKept=0;
1946   fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept);
1947   cellIdsKept->setName(getName());
1948   return cellIdsKept;
1949 }
1950
1951 /*!
1952  * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
1953  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
1954  * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
1955  * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
1956  *
1957  * \param [in] begin input start of array of node ids.
1958  * \param [in] end input end of array of node ids.
1959  * \param [in] fullyIn input that specifies if all node ids must be in ['begin','end') array to consider cell to be in.
1960  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
1961  */
1962 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
1963 {
1964   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
1965   checkConnectivityFullyDefined();
1966   int tmp=-1;
1967   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
1968   std::vector<bool> fastFinder(sz,false);
1969   for(const int *work=begin;work!=end;work++)
1970     if(*work>=0 && *work<sz)
1971       fastFinder[*work]=true;
1972   int nbOfCells=getNumberOfCells();
1973   const int *conn=getNodalConnectivity()->getConstPointer();
1974   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
1975   for(int i=0;i<nbOfCells;i++)
1976     {
1977       int ref=0,nbOfHit=0;
1978       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
1979         if(*work2>=0)
1980           {
1981             ref++;
1982             if(fastFinder[*work2])
1983               nbOfHit++;
1984           }
1985       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
1986         cellIdsKept->pushBackSilent(i);
1987     }
1988   cellIdsKeptArr=cellIdsKept.retn();
1989 }
1990
1991 /*!
1992  * This method is very close too MEDCouplingUMesh::buildPartOfMySelfNode. The difference is that it returns directly ids.
1993  */
1994 DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
1995 {
1996   DataArrayInt *cellIdsKept=0;
1997   fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
1998   cellIdsKept->setName(getName());
1999   return cellIdsKept;
2000 }
2001
2002 /*!
2003  * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
2004  * The return newly allocated mesh will share the same coordinates as 'this'.
2005  * Parameter 'fullyIn' specifies if a cell that has part of its nodes in ids array is kept or not.
2006  * If 'fullyIn' is true only cells whose ids are \b fully contained in ['begin','end') tab will be kept.
2007  */
2008 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2009 {
2010   DataArrayInt *cellIdsKept=0;
2011   fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2012   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept2(cellIdsKept);
2013   return buildPartOfMySelf(cellIdsKept->begin(),cellIdsKept->end(),true);
2014 }
2015
2016 /*!
2017  * Contrary to MEDCouplingUMesh::buildPartOfMySelfNode method this method builds a mesh with a meshDimension equal to
2018  * this->getMeshDimension()-1. The return newly allocated mesh will share the same coordinates as 'this'.
2019  * Parameter 'fullyIn' specifies if a face that has part of its nodes in ids array is kept or not.
2020  * If 'fullyIn' is true only faces whose ids are \b fully contained in ['begin','end') tab will be kept.
2021  */
2022 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2023 {
2024   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2025   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2026   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2027   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2028   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2029 }
2030
2031 /*!
2032  * This method returns a mesh with meshDim=this->getMeshDimension()-1.
2033  * This returned mesh contains cells that are linked with one and only one cell of this.
2034  * @param keepCoords specifies if ParaMEDMEM::MEDCouplingUMesh::zipCoords is called on returned mesh before being returned. If true zipCoords is \b NOT called, if false, zipCoords is called.
2035  * @return mesh with ref counter equal to 1.
2036  */
2037 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2038 {
2039   DataArrayInt *desc=DataArrayInt::New();
2040   DataArrayInt *descIndx=DataArrayInt::New();
2041   DataArrayInt *revDesc=DataArrayInt::New();
2042   DataArrayInt *revDescIndx=DataArrayInt::New();
2043   //
2044   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2045   revDesc->decrRef();
2046   desc->decrRef();
2047   descIndx->decrRef();
2048   int nbOfCells=meshDM1->getNumberOfCells();
2049   const int *revDescIndxC=revDescIndx->getConstPointer();
2050   std::vector<int> boundaryCells;
2051   for(int i=0;i<nbOfCells;i++)
2052     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2053       boundaryCells.push_back(i);
2054   revDescIndx->decrRef();
2055   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2056   return ret;
2057 }
2058
2059 /*!
2060  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2061  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2062  * This method makes the assumption that 'this' is fully defined (coords,connectivity). If not an exception will be thrown. 
2063  */
2064 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2065 {
2066   checkFullyDefined();
2067   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2068   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2069   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2070   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2071   //
2072   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2073   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2074   //
2075   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2076   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2077   const int *revDescPtr=revDesc->getConstPointer();
2078   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2079   int nbOfCells=getNumberOfCells();
2080   std::vector<bool> ret1(nbOfCells,false);
2081   int sz=0;
2082   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2083     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2084       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2085   //
2086   DataArrayInt *ret2=DataArrayInt::New();
2087   ret2->alloc(sz,1);
2088   int *ret2Ptr=ret2->getPointer();
2089   sz=0;
2090   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2091     if(*it)
2092       *ret2Ptr++=sz;
2093   ret2->setName("BoundaryCells");
2094   return ret2;
2095 }
2096
2097 /*!
2098  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2099  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2100  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2101  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2102  *
2103  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2104  * This method method returns cells ids set s = s1 + s2 where :
2105  * 
2106  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2107  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2108  *
2109  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2110  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2111  *
2112  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2113  * \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
2114  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2115  */
2116 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2117 {
2118   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2119     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2120   checkConnectivityFullyDefined();
2121   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2122   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2123     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2124   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2125   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2126   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2127   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2128   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2129   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2130   DataArrayInt *idsOtherInConsti=0;
2131   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2132   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2133   if(!b)
2134     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2135   std::set<int> s1;
2136   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2137     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2138   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2139   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2140   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2141   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2142   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2143   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2144   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2145   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2146   neighThisPartAuto=0;
2147   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2148   const int li[2]={0,1};
2149   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2150   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2151   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2152   s_renum1->sort();
2153   //
2154   cellIdsRk0=s0arr.retn();
2155   cellIdsRk1=s_renum1.retn();
2156 }
2157
2158 /*!
2159  * 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
2160  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2161  * 
2162  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2163  */
2164 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2165 {
2166   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2167   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2168   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2169   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2170   //
2171   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2172   revDesc=0; desc=0; descIndx=0;
2173   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2174   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2175   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2176 }
2177
2178 /*!
2179  * This methods returns set of nodes in a newly allocated array that the caller has to deal with.
2180  * The returned nodes ids are those lying on the boundary of \b this.
2181  */
2182 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2183 {
2184   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2185   return skin->computeFetchedNodeIds();
2186 }
2187
2188 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2189 {
2190   incrRef();
2191   return const_cast<MEDCouplingUMesh *>(this);
2192 }
2193
2194 /*
2195  * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
2196  * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
2197  * This value is asked because often known by the caller of this method.
2198  * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
2199  *
2200  * @param newNodeNumbers array specifying the new numbering in old2New convention.
2201  * @param newNbOfNodes the new number of nodes.
2202  */
2203 void MEDCouplingUMesh::renumberNodes(const int *newNodeNumbers, int newNbOfNodes)
2204 {
2205   MEDCouplingPointSet::renumberNodes(newNodeNumbers,newNbOfNodes);
2206   renumberNodesInConn(newNodeNumbers);
2207 }
2208
2209 /*
2210  * This method renumber 'this' using 'newNodeNumbers' array of size this->getNumberOfNodes.
2211  * newNbOfNodes specifies the *std::max_element(newNodeNumbers,newNodeNumbers+this->getNumberOfNodes())
2212  * This value is asked because often known by the caller of this method.
2213  * This method, contrary to MEDCouplingMesh::renumberCells does NOT conserve the number of nodes before and after.
2214  * The difference with ParaMEDMEM::MEDCouplingUMesh::renumberNodes method is in the fact that the barycenter of merged nodes is computed here.
2215  *
2216  * @param newNodeNumbers array specifying the new numbering.
2217  * @param newNbOfNodes the new number of nodes.
2218  *
2219  */
2220 void MEDCouplingUMesh::renumberNodes2(const int *newNodeNumbers, int newNbOfNodes)
2221 {
2222   MEDCouplingPointSet::renumberNodes2(newNodeNumbers,newNbOfNodes);
2223   renumberNodesInConn(newNodeNumbers);
2224 }
2225
2226 /*!
2227  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2228  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2229  * 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.
2230  * 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.
2231  * 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.
2232  *
2233  * \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
2234  *             parameter is altered during the call.
2235  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2236  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2237  * \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.
2238  *
2239  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2240  */
2241 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2242                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2243 {
2244   checkFullyDefined();
2245   otherDimM1OnSameCoords.checkFullyDefined();
2246   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2247     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2248   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2249     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2250   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2251   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2252   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2253   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2254   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2255   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2256   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2257   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2258   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2259   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2260   //
2261   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2262   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2263   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2264   DataArrayInt *idsTmp=0;
2265   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2266   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2267   if(!b)
2268     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2269   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2270   DataArrayInt *tmp0=0,*tmp1=0;
2271   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2272   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2273   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2274   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2275   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2276   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2277   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2278   //
2279   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2280   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2281   nodeIdsToDuplicate=s3.retn();
2282 }
2283
2284 /*!
2285  * This method operates a modification of the connectivity and coords in \b this.
2286  * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this 
2287  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2288  * 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
2289  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2290  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2291  * 
2292  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2293  * 
2294  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2295  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2296  */
2297 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2298 {
2299   int nbOfNodes=getNumberOfNodes();
2300   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2301   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2302 }
2303
2304 /*!
2305  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2306  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2307  * This method is an generalization of \ref ParaMEDMEM::MEDCouplingUMesh::shiftNodeNumbersInConn "shiftNodeNumbersInConn method".
2308  * @param [in] newNodeNumbers in old2New convention
2309  */
2310 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2311 {
2312   checkConnectivityFullyDefined();
2313   int *conn=getNodalConnectivity()->getPointer();
2314   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2315   int nbOfCells=getNumberOfCells();
2316   for(int i=0;i<nbOfCells;i++)
2317     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2318       {
2319         int& node=conn[iconn];
2320         if(node>=0)//avoid polyhedron separator
2321           {
2322             node=newNodeNumbersO2N[node];
2323           }
2324       }
2325   _nodal_connec->declareAsNew();
2326   updateTime();
2327 }
2328
2329 /*!
2330  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2331  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2332  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2333  * 
2334  * @param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2335  */
2336 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2337 {
2338   checkConnectivityFullyDefined();
2339   int *conn=getNodalConnectivity()->getPointer();
2340   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2341   int nbOfCells=getNumberOfCells();
2342   for(int i=0;i<nbOfCells;i++)
2343     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2344       {
2345         int& node=conn[iconn];
2346         if(node>=0)//avoid polyhedron separator
2347           {
2348             node+=delta;
2349           }
2350       }
2351   _nodal_connec->declareAsNew();
2352   updateTime();
2353 }
2354
2355 /*!
2356  * This method operates a modification of the connectivity in \b this.
2357  * 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.
2358  * Every time that a node id in [\b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd) will append in nodal connectivity of \b this 
2359  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2360  * 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
2361  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2362  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2363  * 
2364  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2365  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2366  * 
2367  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2368  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2369  * \param [in] offset the offset applied to all node ids in connectivity that are in [nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd). 
2370  */
2371 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2372 {
2373   checkConnectivityFullyDefined();
2374   std::map<int,int> m;
2375   int val=offset;
2376   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2377     m[*work]=val;
2378   int *conn=getNodalConnectivity()->getPointer();
2379   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2380   int nbOfCells=getNumberOfCells();
2381   for(int i=0;i<nbOfCells;i++)
2382     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2383       {
2384         int& node=conn[iconn];
2385         if(node>=0)//avoid polyhedron separator
2386           {
2387             std::map<int,int>::iterator it=m.find(node);
2388             if(it!=m.end())
2389               node=(*it).second;
2390           }
2391       }
2392   updateTime();
2393 }
2394
2395 /*!
2396  * This method renumbers cells of 'this' using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2397  *
2398  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2399  * After the call of this method the number of cells remains the same as before.
2400  *
2401  * If 'check' equals true the method will check that any elements in [old2NewBg;old2NewEnd) is unique ; if not
2402  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [old2NewBg;old2NewEnd) is not expected to
2403  * be strictly in [0;this->getNumberOfCells()).
2404  *
2405  * If 'check' equals false the method will not check the content of [old2NewBg;old2NewEnd).
2406  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [old2NewBg;old2NewEnd) should be unique and
2407  * should be contained in[0;this->getNumberOfCells()).
2408  * 
2409  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2410  */
2411 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2412 {
2413   checkConnectivityFullyDefined();
2414   int nbCells=getNumberOfCells();
2415   const int *array=old2NewBg;
2416   if(check)
2417     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2418   //
2419   const int *conn=_nodal_connec->getConstPointer();
2420   const int *connI=_nodal_connec_index->getConstPointer();
2421   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2422   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2423   newConn->copyStringInfoFrom(*_nodal_connec);
2424   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2425   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2426   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2427   //
2428   int *newC=newConn->getPointer();
2429   int *newCI=newConnI->getPointer();
2430   int loc=0;
2431   newCI[0]=loc;
2432   for(int i=0;i<nbCells;i++)
2433     {
2434       std::size_t pos=std::distance(array,std::find(array,array+nbCells,i));
2435       int nbOfElts=connI[pos+1]-connI[pos];
2436       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2437       loc+=nbOfElts;
2438       newCI[i+1]=loc;
2439     }
2440   //
2441   setConnectivity(newConn,newConnI);
2442   if(check)
2443     delete [] const_cast<int *>(array);
2444 }
2445
2446 /*!
2447  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox'.
2448  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2449  * added in 'elems' parameter.
2450  */
2451 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2452 {
2453   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2454   if(getMeshDimension()==-1)
2455     {
2456       elems->pushBackSilent(0);
2457       return elems.retn();
2458     }
2459   int dim=getSpaceDimension();
2460   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2461   const int* conn      = getNodalConnectivity()->getConstPointer();
2462   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2463   const double* coords = getCoords()->getConstPointer();
2464   int nbOfCells=getNumberOfCells();
2465   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2466     {
2467       for (int i=0; i<dim; i++)
2468         {
2469           elem_bb[i*2]=std::numeric_limits<double>::max();
2470           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2471         }
2472
2473       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2474         {
2475           int node= conn[inode];
2476           if(node>=0)//avoid polyhedron separator
2477             {
2478               for (int idim=0; idim<dim; idim++)
2479                 {
2480                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2481                     {
2482                       elem_bb[idim*2] = coords[node*dim+idim] ;
2483                     }
2484                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2485                     {
2486                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2487                     }
2488                 }
2489             }
2490         }
2491       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2492         elems->pushBackSilent(ielem);
2493     }
2494   return elems.retn();
2495 }
2496
2497 /*!
2498  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2499  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2500  * added in 'elems' parameter.
2501  */
2502 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2503 {
2504   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2505   if(getMeshDimension()==-1)
2506     {
2507       elems->pushBackSilent(0);
2508       return elems.retn();
2509     }
2510   int dim=getSpaceDimension();
2511   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2512   const int* conn      = getNodalConnectivity()->getConstPointer();
2513   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2514   const double* coords = getCoords()->getConstPointer();
2515   int nbOfCells=getNumberOfCells();
2516   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2517     {
2518       for (int i=0; i<dim; i++)
2519         {
2520           elem_bb[i*2]=std::numeric_limits<double>::max();
2521           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2522         }
2523
2524       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2525         {
2526           int node= conn[inode];
2527           if(node>=0)//avoid polyhedron separator
2528             {
2529               for (int idim=0; idim<dim; idim++)
2530                 {
2531                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2532                     {
2533                       elem_bb[idim*2] = coords[node*dim+idim] ;
2534                     }
2535                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2536                     {
2537                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2538                     }
2539                 }
2540             }
2541         }
2542       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2543         elems->pushBackSilent(ielem);
2544     }
2545   return elems.retn();
2546 }
2547
2548 /*!
2549  * Returns the cell type of cell with id 'cellId'.
2550  */
2551 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2552 {
2553   const int *ptI=_nodal_connec_index->getConstPointer();
2554   const int *pt=_nodal_connec->getConstPointer();
2555   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2556     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2557   else
2558     {
2559       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2560       throw INTERP_KERNEL::Exception(oss.str().c_str());
2561     }
2562 }
2563
2564 /*!
2565  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2566  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2567  * The coordinates array is not considered here.
2568  *
2569  * \param [in] type the geometric type
2570  * \return cell ids in this having geometric type \a type.
2571  */
2572 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2573 {
2574   
2575   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2576   ret->alloc(0,1);
2577   checkConnectivityFullyDefined();
2578   int nbCells=getNumberOfCells();
2579   int mdim=getMeshDimension();
2580   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2581   if(mdim!=(int)cm.getDimension())
2582     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2583   const int *ptI=_nodal_connec_index->getConstPointer();
2584   const int *pt=_nodal_connec->getConstPointer();
2585   for(int i=0;i<nbCells;i++)
2586     {
2587       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2588         ret->pushBackSilent(i);
2589     }
2590   return ret.retn();
2591 }
2592
2593 /*!
2594  * Returns nb of cells having the geometric type 'type'.
2595  */
2596 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2597 {
2598   const int *ptI=_nodal_connec_index->getConstPointer();
2599   const int *pt=_nodal_connec->getConstPointer();
2600   int nbOfCells=getNumberOfCells();
2601   int ret=0;
2602   for(int i=0;i<nbOfCells;i++)
2603     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2604       ret++;
2605   return ret;
2606 }
2607
2608 /*!
2609  * Appends the nodal connectivity in 'conn' of cell with id 'cellId'.
2610  * All elements added in conn can be used by MEDCouplingUMesh::getCoordinatesOfNode method.
2611  * That is to say -1 separator is omitted in returned conn.
2612  */
2613 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2614 {
2615   const int *ptI=_nodal_connec_index->getConstPointer();
2616   const int *pt=_nodal_connec->getConstPointer();
2617   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2618     if(*w>=0)
2619       conn.push_back(*w);
2620 }
2621
2622 std::string MEDCouplingUMesh::simpleRepr() const
2623 {
2624   static const char msg0[]="No coordinates specified !";
2625   std::ostringstream ret;
2626   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2627   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2628   int tmpp1,tmpp2;
2629   double tt=getTime(tmpp1,tmpp2);
2630   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2631   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2632   ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : ";
2633   if(_coords!=0)
2634     {
2635       const int spaceDim=getSpaceDimension();
2636       ret << spaceDim << "\nInfo attached on space dimension : ";
2637       for(int i=0;i<spaceDim;i++)
2638         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2639       ret << "\n";
2640     }
2641   else
2642     ret << msg0 << "\n";
2643   ret << "Number of nodes : ";
2644   if(_coords!=0)
2645     ret << getNumberOfNodes() << "\n";
2646   else
2647     ret << msg0 << "\n";
2648   ret << "Number of cells : ";
2649   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2650     ret << getNumberOfCells() << "\n";
2651   else
2652     ret << "No connectivity specified !" << "\n";
2653   ret << "Cell types present : ";
2654   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2655     {
2656       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2657       ret << cm.getRepr() << " ";
2658     }
2659   ret << "\n";
2660   return ret.str();
2661 }
2662
2663 std::string MEDCouplingUMesh::advancedRepr() const
2664 {
2665   std::ostringstream ret;
2666   ret << simpleRepr();
2667   ret << "\nCoordinates array : \n___________________\n\n";
2668   if(_coords)
2669     _coords->reprWithoutNameStream(ret);
2670   else
2671     ret << "No array set !\n";
2672   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2673   reprConnectivityOfThisLL(ret);
2674   return ret.str();
2675 }
2676
2677 /*!
2678  * This method returns a C++ code that is a dump of \a this.
2679  * This method will throw if this is not fully defined.
2680  */
2681 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2682 {
2683   static const char coordsName[]="coords";
2684   static const char connName[]="conn";
2685   static const char connIName[]="connI";
2686   checkFullyDefined();
2687   std::ostringstream ret; ret << "// coordinates" << std::endl;
2688   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2689   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2690   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2691   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2692   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2693   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2694   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2695   return ret.str();
2696 }
2697
2698 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2699 {
2700   std::ostringstream ret;
2701   reprConnectivityOfThisLL(ret);
2702   return ret.str();
2703 }
2704
2705 /*!
2706  * This method builds a newly allocated instance (with the same name than 'this') that the caller has the responsability to deal with.
2707  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2708  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2709  * some algos).
2710  * 
2711  * This method expects that 'this' has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2712  * This method analyzes the 3 arrays of 'this'. For each the following behaviour is done : if the array is null a newly one is created
2713  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2714  */
2715 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2716 {
2717   int mdim=getMeshDimension();
2718   if(mdim<0)
2719     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2720   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2721   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2722   bool needToCpyCT=true;
2723   if(!_nodal_connec)
2724     {
2725       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2726       needToCpyCT=false;
2727     }
2728   else
2729     {
2730       tmp1=_nodal_connec;
2731       tmp1->incrRef();
2732     }
2733   if(!_nodal_connec_index)
2734     {
2735       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2736       needToCpyCT=false;
2737     }
2738   else
2739     {
2740       tmp2=_nodal_connec_index;
2741       tmp2->incrRef();
2742     }
2743   ret->setConnectivity(tmp1,tmp2,false);
2744   if(needToCpyCT)
2745     ret->_types=_types;
2746   if(!_coords)
2747     {
2748       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2749       ret->setCoords(coords);
2750     }
2751   else
2752     ret->setCoords(_coords);
2753   return ret.retn();
2754 }
2755
2756 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2757 {
2758   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2759     {
2760       int nbOfCells=getNumberOfCells();
2761       const int *c=_nodal_connec->getConstPointer();
2762       const int *ci=_nodal_connec_index->getConstPointer();
2763       for(int i=0;i<nbOfCells;i++)
2764         {
2765           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2766           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2767           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2768           stream << "\n";
2769         }
2770     }
2771   else
2772     stream << "Connectivity not defined !\n";
2773 }
2774
2775 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2776 {
2777   const int *ptI=_nodal_connec_index->getConstPointer();
2778   const int *pt=_nodal_connec->getConstPointer();
2779   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2780     return ptI[cellId+1]-ptI[cellId]-1;
2781   else
2782     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2783 }
2784
2785 /*!
2786  * This method is equivalent to MEDCouplingUMesh::getAllTypes excecpt that it returns only types of submesh which cell ids are in [begin,end).
2787  * This method avoids to compute explicitely submesh to get its types.
2788  */
2789 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2790 {
2791   checkFullyDefined();
2792   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2793   const int *conn=_nodal_connec->getConstPointer();
2794   const int *connIndex=_nodal_connec_index->getConstPointer();
2795   for(const int *w=begin;w!=end;w++)
2796     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2797   return ret;
2798 }
2799
2800 /*!
2801  * Method reserved for advanced users having prepared their connectivity before.
2802  * Arrays 'conn' and 'connIndex' will be aggregated without any copy and their counter will be incremented.
2803  */
2804 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2805 {
2806   DataArrayInt::SetArrayIn(conn,_nodal_connec);
2807   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2808   if(isComputingTypes)
2809     computeTypes();
2810   declareAsNew();
2811 }
2812
2813 /*!
2814  * Copy constructor. If 'deepCpy' is false 'this' is a shallow copy of other.
2815  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2816  */
2817 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2818                                                                                  _nodal_connec(0),_nodal_connec_index(0),
2819                                                                                 _types(other._types)
2820 {
2821   if(other._nodal_connec)
2822     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2823   if(other._nodal_connec_index)
2824     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2825 }
2826
2827 MEDCouplingUMesh::~MEDCouplingUMesh()
2828 {
2829   if(_nodal_connec)
2830     _nodal_connec->decrRef();
2831   if(_nodal_connec_index)
2832     _nodal_connec_index->decrRef();
2833 }
2834
2835 /*!
2836  * This method recomputes all cell types of 'this'.
2837  */
2838 void MEDCouplingUMesh::computeTypes()
2839 {
2840   if(_nodal_connec && _nodal_connec_index)
2841     {
2842       _types.clear();
2843       const int *conn=_nodal_connec->getConstPointer();
2844       const int *connIndex=_nodal_connec_index->getConstPointer();
2845       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2846       if (nbOfElem > 0)
2847         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2848           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2849     }
2850 }
2851
2852 /*!
2853  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2854  */
2855 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2856 {
2857   if(!_nodal_connec_index || !_nodal_connec || !_coords)
2858     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2859 }
2860
2861 /*!
2862  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2863  */
2864 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2865 {
2866   if(!_nodal_connec_index || !_nodal_connec)
2867     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2868 }
2869
2870 int MEDCouplingUMesh::getNumberOfCells() const
2871
2872   if(_nodal_connec_index)
2873     return _nodal_connec_index->getNumberOfTuples()-1;
2874   else
2875     if(_mesh_dim==-1)
2876       return 1;
2877     else
2878       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
2879 }
2880
2881 int MEDCouplingUMesh::getMeshDimension() const
2882 {
2883   if(_mesh_dim<-1)
2884     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
2885   return _mesh_dim;
2886 }
2887
2888 /*!
2889  * This method is for test reason. Normally the integer returned is not useable by user.
2890  */
2891 int MEDCouplingUMesh::getMeshLength() const
2892 {
2893   return _nodal_connec->getNbOfElems();
2894 }
2895
2896 /*!
2897  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
2898  */
2899 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
2900 {
2901   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
2902   tinyInfo.push_back(getMeshDimension());
2903   tinyInfo.push_back(getNumberOfCells());
2904   if(_nodal_connec)
2905     tinyInfo.push_back(getMeshLength());
2906   else
2907     tinyInfo.push_back(-1);
2908 }
2909
2910 /*!
2911  * First step of unserialization process.
2912  */
2913 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
2914 {
2915   return tinyInfo[6]<=0;
2916 }
2917
2918 /*!
2919  * Second step of serialization process.
2920  * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
2921  */
2922 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
2923 {
2924   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
2925   if(tinyInfo[5]!=-1)
2926     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
2927 }
2928
2929 /*!
2930  * Third and final step of serialization process.
2931  */
2932 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
2933 {
2934   MEDCouplingPointSet::serialize(a1,a2);
2935   if(getMeshDimension()>-1)
2936     {
2937       a1=DataArrayInt::New();
2938       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
2939       int *ptA1=a1->getPointer();
2940       const int *conn=getNodalConnectivity()->getConstPointer();
2941       const int *index=getNodalConnectivityIndex()->getConstPointer();
2942       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
2943       std::copy(conn,conn+getMeshLength(),ptA1);
2944     }
2945   else
2946     a1=0;
2947 }
2948
2949 /*!
2950  * Second and final unserialization process.
2951  * @param tinyInfo must be equal to the result given by getTinySerializationInformation method.
2952  */
2953 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
2954 {
2955   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
2956   setMeshDimension(tinyInfo[5]);
2957   if(tinyInfo[7]!=-1)
2958     {
2959       // Connectivity
2960       const int *recvBuffer=a1->getConstPointer();
2961       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
2962       myConnecIndex->alloc(tinyInfo[6]+1,1);
2963       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
2964       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
2965       myConnec->alloc(tinyInfo[7],1);
2966       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
2967       setConnectivity(myConnec, myConnecIndex);
2968     }
2969 }
2970
2971 /*!
2972  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
2973  * CellIds are given using range specified by a start an end and step.
2974  */
2975 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
2976 {
2977   checkFullyDefined();
2978   int ncell=getNumberOfCells();
2979   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
2980   ret->_mesh_dim=_mesh_dim;
2981   ret->setCoords(_coords);
2982   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
2983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
2984   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
2985   int work=start;
2986   const int *conn=_nodal_connec->getConstPointer();
2987   const int *connIndex=_nodal_connec_index->getConstPointer();
2988   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
2989     {
2990       if(work>=0 && work<ncell)
2991         {
2992           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
2993         }
2994       else
2995         {
2996           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
2997           throw INTERP_KERNEL::Exception(oss.str().c_str());
2998         }
2999     }
3000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3001   int *newConnPtr=newConn->getPointer();
3002   std::set<INTERP_KERNEL::NormalizedCellType> types;
3003   work=start;
3004   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3005     {
3006       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3007       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3008     }
3009   ret->setConnectivity(newConn,newConnI,false);
3010   ret->_types=types;
3011   ret->copyTinyInfoFrom(this);
3012   return ret.retn();
3013 }
3014
3015 /*!
3016  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3017  * Keeps from 'this' only cells which constituing point id are in the ids specified by ['begin','end').
3018  * The return newly allocated mesh will share the same coordinates as 'this'.
3019  */
3020 MEDCouplingUMesh *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3021 {
3022   checkFullyDefined();
3023   int ncell=getNumberOfCells();
3024   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3025   ret->_mesh_dim=_mesh_dim;
3026   ret->setCoords(_coords);
3027   std::size_t nbOfElemsRet=std::distance(begin,end);
3028   int *connIndexRet=new int[nbOfElemsRet+1];
3029   connIndexRet[0]=0;
3030   const int *conn=_nodal_connec->getConstPointer();
3031   const int *connIndex=_nodal_connec_index->getConstPointer();
3032   int newNbring=0;
3033   for(const int *work=begin;work!=end;work++,newNbring++)
3034     {
3035       if(*work>=0 && *work<ncell)
3036         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3037       else
3038         {
3039           delete [] connIndexRet;
3040           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3041           throw INTERP_KERNEL::Exception(oss.str().c_str());
3042         }
3043     }
3044   int *connRet=new int[connIndexRet[nbOfElemsRet]];
3045   int *connRetWork=connRet;
3046   std::set<INTERP_KERNEL::NormalizedCellType> types;
3047   for(const int *work=begin;work!=end;work++)
3048     {
3049       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3050       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3051     }
3052   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3053   connRetArr->useArray(connRet,true,CPP_DEALLOC,connIndexRet[nbOfElemsRet],1);
3054   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3055   connIndexRetArr->useArray(connIndexRet,true,CPP_DEALLOC,(int)nbOfElemsRet+1,1);
3056   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3057   ret->_types=types;
3058   ret->copyTinyInfoFrom(this);
3059   return ret.retn();
3060 }
3061
3062 /*!
3063  * brief returns the volumes of the cells underlying the field \a field
3064  *
3065  * For 2D geometries, the returned field contains the areas.
3066  * For 3D geometries, the returned field contains the volumes.
3067  *
3068  * param field field on which cells the volumes are required
3069  * return field containing the volumes, area or length depending the meshdimension.
3070  */
3071 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3072 {
3073   std::string name="MeasureOfMesh_";
3074   name+=getName();
3075   int nbelem=getNumberOfCells();
3076   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3077   field->setName(name.c_str());
3078   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3079   array->alloc(nbelem,1);
3080   double *area_vol=array->getPointer();
3081   field->setArray(array) ; array=0;
3082   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3083   field->synchronizeTimeWithMesh();
3084   if(getMeshDimension()!=-1)
3085     {
3086       int ipt;
3087       INTERP_KERNEL::NormalizedCellType type;
3088       int dim_space=getSpaceDimension();
3089       const double *coords=getCoords()->getConstPointer();
3090       const int *connec=getNodalConnectivity()->getConstPointer();
3091       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3092       for(int iel=0;iel<nbelem;iel++)
3093         {
3094           ipt=connec_index[iel];
3095           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3096           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);
3097         }
3098       if(isAbs)
3099         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3100     }
3101   else
3102     {
3103       area_vol[0]=std::numeric_limits<double>::max();
3104     }
3105   return field.retn();
3106 }
3107
3108 /*!
3109  * This method is equivalent to MEDCouplingUMesh::getMeasureField except that only part defined by [begin,end) is returned !
3110  * This method avoids to build explicitely part of this to perform the work.
3111  */
3112 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3113 {
3114   std::string name="PartMeasureOfMesh_";
3115   name+=getName();
3116   int nbelem=(int)std::distance(begin,end);
3117   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3118   array->setName(name.c_str());
3119   array->alloc(nbelem,1);
3120   double *area_vol=array->getPointer();
3121   if(getMeshDimension()!=-1)
3122     {
3123       int ipt;
3124       INTERP_KERNEL::NormalizedCellType type;
3125       int dim_space=getSpaceDimension();
3126       const double *coords=getCoords()->getConstPointer();
3127       const int *connec=getNodalConnectivity()->getConstPointer();
3128       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3129       for(const int *iel=begin;iel!=end;iel++)
3130         {
3131           ipt=connec_index[*iel];
3132           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3133           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3134         }
3135       if(isAbs)
3136         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3137     }
3138   else
3139     {
3140       area_vol[0]=std::numeric_limits<double>::max();
3141     }
3142   return array.retn();
3143 }
3144
3145 /*!
3146  * This methods returns a field on nodes and no time. This method is useful to check "P1*" conservative interpolators.
3147  * This field returns the getMeasureField of the dualMesh in P1 sens of 'this'.
3148  */
3149 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3150 {
3151   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3152   std::string name="MeasureOnNodeOfMesh_";
3153   name+=getName();
3154   int nbNodes=getNumberOfNodes();
3155   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3156   double cst=1./((double)getMeshDimension()+1.);
3157   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3158   array->alloc(nbNodes,1);
3159   double *valsToFill=array->getPointer();
3160   std::fill(valsToFill,valsToFill+nbNodes,0.);
3161   const double *values=tmp->getArray()->getConstPointer();
3162   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3163   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3164   getReverseNodalConnectivity(da,daInd);
3165   const int *daPtr=da->getConstPointer();
3166   const int *daIPtr=daInd->getConstPointer();
3167   for(int i=0;i<nbNodes;i++)
3168     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3169       valsToFill[i]+=cst*values[*cell];
3170   ret->setMesh(this);
3171   ret->setArray(array);
3172   return ret.retn();
3173 }
3174
3175 /*!
3176  * This methods returns a vector field on cells that represents the orthogonal vector normalized of each 2D cell of this.
3177  * This method is only callable on mesh with meshdim == 2 and spacedim==2 or 3.
3178  */
3179 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3180 {
3181   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3182     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3183   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3184   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3185   int nbOfCells=getNumberOfCells();
3186   int nbComp=getMeshDimension()+1;
3187   array->alloc(nbOfCells,nbComp);
3188   double *vals=array->getPointer();
3189   const int *connI=_nodal_connec_index->getConstPointer();
3190   const int *conn=_nodal_connec->getConstPointer();
3191   const double *coords=_coords->getConstPointer();
3192   if(getMeshDimension()==2)
3193     {
3194       if(getSpaceDimension()==3)
3195         {
3196           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3197           const double *locPtr=loc->getConstPointer();
3198           for(int i=0;i<nbOfCells;i++,vals+=3)
3199             {
3200               int offset=connI[i];
3201               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3202               double n=INTERP_KERNEL::norm<3>(vals);
3203               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3204             }
3205         }
3206       else
3207         {
3208           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3209           const double *isAbsPtr=isAbs->getArray()->begin();
3210           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3211             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3212         }
3213     }
3214   else//meshdimension==1
3215     {
3216       double tmp[2];
3217       for(int i=0;i<nbOfCells;i++)
3218         {
3219           int offset=connI[i];
3220           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3221           double n=INTERP_KERNEL::norm<2>(tmp);
3222           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3223           *vals++=-tmp[1];
3224           *vals++=tmp[0];
3225         }
3226     }
3227   ret->setArray(array);
3228   ret->setMesh(this);
3229   ret->synchronizeTimeWithSupport();
3230   return ret.retn();
3231 }
3232
3233 /*!
3234  * This method is equivalent to MEDCouplingUMesh::buildOrthogonalField except that only part defined by [begin,end) is returned !
3235  * This method avoids to build explicitely part of this to perform the work.
3236  */
3237 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3238 {
3239   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3240     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3241   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3242   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3243   std::size_t nbelems=std::distance(begin,end);
3244   int nbComp=getMeshDimension()+1;
3245   array->alloc((int)nbelems,nbComp);
3246   double *vals=array->getPointer();
3247   const int *connI=_nodal_connec_index->getConstPointer();
3248   const int *conn=_nodal_connec->getConstPointer();
3249   const double *coords=_coords->getConstPointer();
3250   if(getMeshDimension()==2)
3251     {
3252       if(getSpaceDimension()==3)
3253         {
3254           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3255           const double *locPtr=loc->getConstPointer();
3256           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3257             {
3258               int offset=connI[*i];
3259               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3260               double n=INTERP_KERNEL::norm<3>(vals);
3261               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3262             }
3263         }
3264       else
3265         {
3266           for(std::size_t i=0;i<nbelems;i++)
3267             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3268         }
3269     }
3270   else//meshdimension==1
3271     {
3272       double tmp[2];
3273       for(const int *i=begin;i!=end;i++)
3274         {
3275           int offset=connI[*i];
3276           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3277           double n=INTERP_KERNEL::norm<2>(tmp);
3278           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3279           *vals++=-tmp[1];
3280           *vals++=tmp[0];
3281         }
3282     }
3283   ret->setArray(array);
3284   ret->setMesh(this);
3285   ret->synchronizeTimeWithSupport();
3286   return ret.retn();
3287 }
3288
3289 /*!
3290  * This methods returns a vector newly created field on cells that represents the direction vector of each 1D cell of this.
3291  * This method is only callable on mesh with meshdim == 1 containing only SEG2.
3292  */
3293 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3294 {
3295    if(getMeshDimension()!=1)
3296     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3297    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3298      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3299    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3300    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3301    int nbOfCells=getNumberOfCells();
3302    int spaceDim=getSpaceDimension();
3303    array->alloc(nbOfCells,spaceDim);
3304    double *pt=array->getPointer();
3305    const double *coo=getCoords()->getConstPointer();
3306    std::vector<int> conn;
3307    conn.reserve(2);
3308    for(int i=0;i<nbOfCells;i++)
3309      {
3310        conn.resize(0);
3311        getNodeIdsOfCell(i,conn);
3312        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3313      }
3314    ret->setArray(array);
3315    ret->setMesh(this);
3316    ret->synchronizeTimeWithSupport();
3317    return ret.retn();   
3318 }
3319
3320 /*!
3321  * This method expects that 'this' is fully defined and has a spaceDim==3 and a meshDim==3. If it is not the case an exception will be thrown.
3322  * This method returns 2 objects : 
3323  * - a newly created mesh instance containing the result of the slice lying on different coords than 'this' and with a meshdim == 2
3324  * - a newly created dataarray having number of tuples equal to the number of cells in returned mesh that tells for each 2D cell in returned
3325  *   mesh the 3D cell id is 'this' it comes from.
3326  * This method works only for linear meshes (non quadratic).
3327  * If plane crosses within 'eps' a face in 'this' shared by more than 1 cell, 2 output faces will be generated. The 2 faces having the same geometry than intersecting
3328  * face. Only 'cellIds' parameter can distinguish the 2.
3329  * @param origin is the origin of the plane. It should be an array of length 3.
3330  * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3331  * @param eps is the precision. It is used by called method MEDCouplingUMesh::getCellIdsCrossingPlane for the first 3D cell selection (in absolute). 'eps' is
3332  * also used to state if new points should be created or already existing points are reused. 'eps' is also used to tells if plane overlaps a face, edge or nodes (in absolute).
3333  */
3334 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3335 {
3336   checkFullyDefined();
3337   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3338     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3339   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3340   if(candidates->empty())
3341     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3342   std::vector<int> nodes;
3343   DataArrayInt *cellIds1D=0;
3344   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3345   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3346   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3347   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3348   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3349   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3350   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3351   revDesc2=0; revDescIndx2=0;
3352   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3353   revDesc1=0; revDescIndx1=0;
3354   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3355   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3356   //
3357   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3358   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3359     cut3DCurve[*it]=-1;
3360   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3361   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3362   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3363                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3364                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3365   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3366   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3367   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3368   if(cellIds2->empty())
3369     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3370   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3371   ret->setCoords(mDesc1->getCoords());
3372   ret->setConnectivity(conn,connI,true);
3373   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3374   return ret.retn();
3375 }
3376
3377 /*!
3378  * This method expects that 'this' is fully defined and has a spaceDim==3 and a meshDim==2. If it is not the case an exception will be thrown.
3379  * This method returns 2 objects : 
3380  * - a newly created mesh instance containing the result of the slice lying on different coords than 'this' and with a meshdim == 1
3381  * - a newly created dataarray having number of tuples equal to the number of cells in returned mesh that tells for each 2D cell in returned
3382  *   mesh the 3DSurf cell id is 'this' it comes from.
3383  * This method works only for linear meshes (non quadratic).
3384  * If plane crosses within 'eps' a face in 'this' shared by more than 1 cell, 2 output faces will be generated. The 2 faces having the same geometry than intersecting
3385  * face. Only 'cellIds' parameter can distinguish the 2.
3386  * @param origin is the origin of the plane. It should be an array of length 3.
3387  * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3388  * @param eps is the precision. It is used by called method MEDCouplingUMesh::getCellIdsCrossingPlane for the first 3DSurf cell selection (in absolute). 'eps' is
3389  * also used to state if new points should be created or already existing points are reused. 'eps' is also used to tells if plane overlaps a face, edge or nodes (in absolute).
3390  */
3391 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3392 {
3393   checkFullyDefined();
3394   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3395     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3396   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3397   if(candidates->empty())
3398     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3399   std::vector<int> nodes;
3400   DataArrayInt *cellIds1D=0;
3401   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3402   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3403   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3405   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3406   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3407   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3408   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3409   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3410   //
3411   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3412   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3413     cut3DCurve[*it]=-1;
3414   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3415   int ncellsSub=subMesh->getNumberOfCells();
3416   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3417   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3418                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3419                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3420   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3421   conn->alloc(0,1);
3422   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3423   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3424   for(int i=0;i<ncellsSub;i++)
3425     {
3426       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3427         {
3428           if(cut3DSurf[i].first!=-2)
3429             {
3430               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3431               connI->pushBackSilent(conn->getNumberOfTuples());
3432               cellIds2->pushBackSilent(i);
3433             }
3434           else
3435             {
3436               int cellId3DSurf=cut3DSurf[i].second;
3437               int offset=nodalI[cellId3DSurf]+1;
3438               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3439               for(int j=0;j<nbOfEdges;j++)
3440                 {
3441                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3442                   connI->pushBackSilent(conn->getNumberOfTuples());
3443                   cellIds2->pushBackSilent(cellId3DSurf);
3444                 }
3445             }
3446         }
3447     }
3448   if(cellIds2->empty())
3449     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3450   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3451   ret->setCoords(mDesc1->getCoords());
3452   ret->setConnectivity(conn,connI,true);
3453   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3454   return ret.retn();
3455 }
3456
3457 /*!
3458  * This method expects that 'this' is fully defined and has a spaceDim==3. If it is not the case an exception will be thrown.
3459  * This method returns a newly created dataarray containing cellsids in 'this' that potentially crosses the plane specified by 'origin' and 'vec'.
3460  * @param origin is the origin of the plane. It should be an array of length 3.
3461  * @param vec is the direction vector of the plane. It should be an array of length 3. Norm of 'vec' should be > 1e-6.
3462  */
3463 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3464 {
3465   checkFullyDefined();
3466   if(getSpaceDimension()!=3)
3467     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3468   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3469   if(normm<1e-6)
3470     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3471   double vec2[3];
3472   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3473   double angle=acos(vec[2]/normm);
3474   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3475   double bbox[6];
3476   if(angle>eps)
3477     {
3478       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3479       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3480       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3481       mw->setCoords(coo);
3482       mw->getBoundingBox(bbox);
3483       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3484       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3485     }
3486   else
3487     {
3488       getBoundingBox(bbox);
3489       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3490       cellIds=getCellsInBoundingBox(bbox,eps);
3491     }
3492   return cellIds.retn();
3493 }
3494
3495 /*!
3496  * This method checks that 'this' is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3497  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3498  * No consideration of coordinate is done by this method.
3499  * 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)
3500  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3501  */
3502 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3503 {
3504   if(getMeshDimension()!=1)
3505     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3506   int nbCells=getNumberOfCells();
3507   if(nbCells<1)
3508     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3509   const int *connI=_nodal_connec_index->getConstPointer();
3510   const int *conn=_nodal_connec->getConstPointer();
3511   int ref=conn[connI[0]+2];
3512   for(int i=1;i<nbCells;i++)
3513     {
3514       if(conn[connI[i]+1]!=ref)
3515         return false;
3516       ref=conn[connI[i]+2];
3517     }
3518   return true;
3519 }
3520
3521 /*!
3522  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3523  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3524  * @param pt reference point of the line
3525  * @param v normalized director vector of the line
3526  * @param eps max precision before throwing an exception
3527  * @param res output of size this->getNumberOfCells
3528  */
3529 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3530 {
3531   if(getMeshDimension()!=1)
3532     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3533    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3534      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3535    if(getSpaceDimension()!=3)
3536      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3537    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3538    const double *fPtr=f->getArray()->getConstPointer();
3539    double tmp[3];
3540    for(int i=0;i<getNumberOfCells();i++)
3541      {
3542        const double *tmp1=fPtr+3*i;
3543        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3544        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3545        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3546        double n1=INTERP_KERNEL::norm<3>(tmp);
3547        n1/=INTERP_KERNEL::norm<3>(tmp1);
3548        if(n1>eps)
3549          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3550      }
3551    const double *coo=getCoords()->getConstPointer();
3552    for(int i=0;i<getNumberOfNodes();i++)
3553      {
3554        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3555        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3556        res[i]=std::accumulate(tmp,tmp+3,0.);
3557      }
3558 }
3559
3560 /*!
3561  * This method computes the distance from a point \a pt to \a this and the first \a cellId and \a nodeId in \a this corresponding to the returned distance. 
3562  * \a this is expected to be a mesh so that its space dimension is equal to its
3563  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3564  * 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).
3565  * 
3566  * This method firstly find the closer node in \a this to the requested point whose coordinates are defined by [ \a ptBg, \a ptEnd ). Then for this node found 
3567  * the cells sharing this node (if any) are considered to find if the distance to these cell are smaller than the result found previously. If no cells are linked
3568  * to the node that minimizes distance with the input point then -1 is returned in cellId.
3569  *
3570  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3571  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3572  *
3573  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3574  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3575  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3576  * \return the positive value of the distance.
3577  * \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
3578  * dimension - 1.
3579  * \sa DataArrayDouble::distanceToTuple
3580  */
3581 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId, int& nodeId) const throw(INTERP_KERNEL::Exception)
3582 {
3583   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3584   if(meshDim!=spaceDim-1)
3585     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3586   if(meshDim!=2 && meshDim!=1)
3587     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3588   checkFullyDefined();
3589   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3590     { 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()); }
3591   nodeId=-1;
3592   double ret0=_coords->distanceToTuple(ptBg,ptEnd,nodeId);
3593   if(nodeId==-1)
3594     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : something wrong with nodes in this !");
3595   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds=getCellIdsLyingOnNodes(&nodeId,&nodeId+1,false);
3596   switch(meshDim)
3597     {
3598     case 2:
3599       {
3600         distanceToPoint3DSurfAlg(ptBg,cellIds,ret0,cellId);
3601         return ret0;
3602       }
3603     case 1:
3604       {
3605         distanceToPoint2DCurveAlg(ptBg,cellIds,ret0,cellId);
3606         return ret0;
3607       }
3608     default:
3609       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3610     }
3611   
3612   return ret0;
3613 }
3614
3615
3616 /*!
3617  * \param [in] pt the start pointer (included) of the coordinates of the point
3618  * \param [in] cellIds
3619  * \param [in,out] ret0 the min distance between \a this and the external input point
3620  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3621  * \sa MEDCouplingUMesh::distanceToPoint
3622  */
3623 void MEDCouplingUMesh::distanceToPoint3DSurfAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
3624 {
3625   const double *coords=_coords->getConstPointer();
3626   cellId=-1; 
3627   if(cellIds->empty())
3628     return;
3629   const int *ptr=_nodal_connec->getConstPointer();
3630   const int *ptrI=_nodal_connec_index->getConstPointer();
3631   for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
3632     {
3633       switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
3634         {
3635         case INTERP_KERNEL::NORM_TRI3:
3636           {
3637             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*ptr[ptrI[*zeCell]+1],coords+3*ptr[ptrI[*zeCell]+2],coords+3*ptr[ptrI[*zeCell]+3]);
3638             if(tmp<ret0)
3639               { ret0=tmp; cellId=*zeCell; }
3640             break;
3641           }
3642         case INTERP_KERNEL::NORM_QUAD4:
3643         case INTERP_KERNEL::NORM_POLYGON:
3644           {
3645             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,ptr+ptrI[*zeCell]+1,ptr+ptrI[*zeCell+1],coords);
3646             if(tmp<ret0)
3647               { ret0=tmp; cellId=*zeCell; }
3648             break;
3649           }
3650         default:
3651           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3652         }
3653     }
3654 }
3655
3656 /*!
3657  * \param [in] pt the start pointer (included) of the coordinates of the point
3658  * \param [in] cellIds
3659  * \param [in,out] ret0 the min distance between \a this and the external input point
3660  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3661  * \sa MEDCouplingUMesh::distanceToPoint
3662  */
3663 void MEDCouplingUMesh::distanceToPoint2DCurveAlg(const double *pt, const DataArrayInt *cellIds, double& ret0, int& cellId) const throw(INTERP_KERNEL::Exception)
3664 {
3665   const double *coords=_coords->getConstPointer();
3666   if(cellIds->empty())
3667     { cellId=-1; return; }
3668   const int *ptr=_nodal_connec->getConstPointer();
3669   const int *ptrI=_nodal_connec_index->getConstPointer();
3670   for(const int *zeCell=cellIds->begin();zeCell!=cellIds->end();zeCell++)
3671     {
3672        switch((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[*zeCell]])
3673         {
3674         case INTERP_KERNEL::NORM_SEG2:
3675           {
3676             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*ptr[ptrI[*zeCell]+1],coords+2*ptr[ptrI[*zeCell]+2]);
3677             if(tmp!=std::numeric_limits<double>::max()) tmp=sqrt(tmp);
3678             if(tmp<ret0)
3679               { ret0=tmp; cellId=*zeCell; }
3680             break;
3681           }
3682         default:
3683           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3684         }
3685     }
3686 }
3687
3688 /*!
3689  * Returns a cell if any that contains the point located on 'pos' with precison eps.
3690  * If 'pos' is outside 'this' -1 is returned. If several cells contain this point the cell with the smallest id is returned.
3691  * \b Warning this method is good if the caller intends to evaluate only one point. But if more than one point is requested on 'this'
3692  * it is better to use MEDCouplingUMesh::getCellsContainingPoints method because in this case, the acceleration structure will be computed only once.
3693  */
3694 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
3695 {
3696   std::vector<int> elts;
3697   getCellsContainingPoint(pos,eps,elts);
3698   if(elts.empty())
3699     return -1;
3700   return elts.front();
3701 }
3702
3703 /*!
3704  * Returns all cellIds in 'elts' of point 'pos' with eps accuracy.
3705  * \b Warning this method is good if the caller intends to evaluate only one point. But if more than one point is requested on 'this'
3706  * it is better to use MEDCouplingUMesh::getCellsContainingPoints method because in this case, the acceleration structure will be computed only once.
3707  */
3708 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
3709 {
3710   std::vector<int> eltsIndex;
3711   getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
3712 }
3713
3714 /// @cond INTERNAL
3715
3716 namespace ParaMEDMEM
3717 {
3718   template<const int SPACEDIMM>
3719   class DummyClsMCUG
3720   {
3721   public:
3722     static const int MY_SPACEDIM=SPACEDIMM;
3723     static const int MY_MESHDIM=8;
3724     typedef int MyConnType;
3725     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
3726     // begin
3727     // useless, but for windows compilation ...
3728     const double* getCoordinatesPtr() const { return 0; }
3729     const int* getConnectivityPtr() const { return 0; }
3730     const int* getConnectivityIndexPtr() const { return 0; }
3731     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
3732     // end
3733   };
3734
3735   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
3736   {
3737     INTERP_KERNEL::Edge *ret=0;
3738     switch(typ)
3739       {
3740       case INTERP_KERNEL::NORM_SEG2:
3741         {
3742           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
3743           break;
3744         }
3745       case INTERP_KERNEL::NORM_SEG3:
3746         {
3747           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
3748           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
3749           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
3750           bool colinearity=inters.areColinears();
3751           delete e1; delete e2;
3752           if(colinearity)
3753             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
3754           else
3755             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
3756           mapp2[bg[2]].second=false;
3757           break;
3758         }
3759       default:
3760         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
3761       }
3762     return ret;
3763   }
3764
3765   /*!
3766    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed be the sub set of cells in 'candidates' and the global mesh 'mDesc'.
3767    * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
3768    * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
3769    */
3770   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
3771   {
3772     mapp.clear();
3773     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.
3774     const double *coo=mDesc->getCoords()->getConstPointer();
3775     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
3776     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
3777     std::set<int> s;
3778     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
3779       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
3780     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
3781       {
3782         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
3783         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
3784       }
3785     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
3786     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
3787       {
3788         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
3789         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
3790       }
3791     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
3792       {
3793         if((*it2).second.second)
3794           mapp[(*it2).second.first]=(*it2).first;
3795         ((*it2).second.first)->decrRef();
3796       }
3797     return ret;
3798   }
3799
3800   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
3801   {
3802     if(nodeId>=offset2)
3803       {
3804         int locId=nodeId-offset2;
3805         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
3806       }
3807     if(nodeId>=offset1)
3808       {
3809         int locId=nodeId-offset1;
3810         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
3811       }
3812     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
3813   }
3814
3815   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
3816                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
3817                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
3818   {
3819     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
3820       {
3821         int eltId1=abs(*desc1)-1;
3822         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
3823           {
3824             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
3825             if(it==mappRev.end())
3826               {
3827                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
3828                 mapp[node]=*it1;
3829                 mappRev[*it1]=node;
3830               }
3831           }
3832       }
3833   }
3834 }
3835
3836 /// @endcond
3837
3838 template<int SPACEDIM>
3839 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
3840                                                    double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
3841 {
3842   std::vector<double> bbox;
3843   eltsIndex.resize(nbOfPoints+1);
3844   eltsIndex[0]=0;
3845   elts.clear();
3846   getBoundingBoxForBBTree(bbox);
3847   int nbOfCells=getNumberOfCells();
3848   const int *conn=_nodal_connec->getConstPointer();
3849   const int *connI=_nodal_connec_index->getConstPointer();
3850   double bb[2*SPACEDIM];
3851   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
3852   for(int i=0;i<nbOfPoints;i++)
3853     {
3854       eltsIndex[i+1]=eltsIndex[i];
3855       for(int j=0;j<SPACEDIM;j++)
3856         {
3857           bb[2*j]=pos[SPACEDIM*i+j];
3858           bb[2*j+1]=pos[SPACEDIM*i+j];
3859         }
3860       std::vector<int> candidates;
3861       myTree.getIntersectingElems(bb,candidates);
3862       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
3863         {
3864           int sz=connI[(*iter)+1]-connI[*iter]-1;
3865           if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
3866                                                                                                (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
3867                                                                                                coords,conn+connI[*iter]+1,sz,eps))
3868             {
3869               eltsIndex[i+1]++;
3870               elts.push_back(*iter);
3871             }
3872         }
3873     }
3874 }
3875
3876 /*!
3877  * This method is an extension of MEDCouplingUMesh::getCellContainingPoint and MEDCouplingUMesh::getCellsContainingPoint.
3878  * This method performs 'nbOfPoints' time the getCellsContainingPoint request. This method is recommended rather than the 2 others
3879  * in case of multi points searching.
3880  * This method returns 2 arrays 'elts' and 'eltsIndex'. 'eltsIndex' is of size 'nbOfPoints+1' and 'elts' is of size 'eltsIndex[nbOfPoints-1]'.
3881  * For point j in [0,nbOfPoints), (eltsIndex[j+1]-eltsIndex[j]) cells contain this point. These cells are : [elts.begin()+eltsIndex[j],elts.begin():eltsIndex[j+1]).
3882  * 
3883  * \param pos input parameter that points to an array of size 'getSpaceDim()*nbOfPoints' points stored in full interlace mode : X0,Y0,Z0,X1,Y1,Z1...
3884  */
3885 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
3886                                                 std::vector<int>& elts, std::vector<int>& eltsIndex) const
3887 {
3888   int spaceDim=getSpaceDimension();
3889   int mDim=getMeshDimension();
3890   if(spaceDim==3)
3891     {
3892       if(mDim==3)
3893         {
3894           const double *coords=_coords->getConstPointer();
3895           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3896         }
3897       /*else if(mDim==2)
3898         {
3899           
3900         }*/
3901       else
3902         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
3903     }
3904   else if(spaceDim==2)
3905     {
3906       if(mDim==2)
3907         {
3908           const double *coords=_coords->getConstPointer();
3909           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3910         }
3911       else
3912         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
3913     }
3914   else if(spaceDim==1)
3915     {
3916       if(mDim==1)
3917         {
3918           const double *coords=_coords->getConstPointer();
3919           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
3920         }
3921       else
3922         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
3923     }
3924   else
3925     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
3926 }
3927
3928 /*!
3929  * This method is only available for a mesh with meshDim==2 and spaceDim==2||spaceDim==3.
3930  * This method returns a vector 'cells' where all detected butterfly cells have been added to cells.
3931  * A 2D cell is considered to be butterfly if it exists at least one pair of distinct edges of it that intersect each other
3932  * anywhere excepted their extremities. An INTERP_KERNEL::NORM_NORI3 could \b not be butterfly.
3933  */
3934 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
3935 {
3936   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
3937   if(getMeshDimension()!=2)
3938     throw INTERP_KERNEL::Exception(msg);
3939   int spaceDim=getSpaceDimension();
3940   if(spaceDim!=2 && spaceDim!=3)
3941     throw INTERP_KERNEL::Exception(msg);
3942   const int *conn=_nodal_connec->getConstPointer();
3943   const int *connI=_nodal_connec_index->getConstPointer();
3944   int nbOfCells=getNumberOfCells();
3945   std::vector<double> cell2DinS2;
3946   for(int i=0;i<nbOfCells;i++)
3947     {
3948       int offset=connI[i];
3949       int nbOfNodesForCell=connI[i+1]-offset-1;
3950       if(nbOfNodesForCell<=3)
3951         continue;
3952       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
3953       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
3954       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
3955         cells.push_back(i);
3956       cell2DinS2.clear();
3957     }
3958 }
3959
3960 /*!
3961  * This method is typically requested to unbutterfly 2D linear cells in \b this.
3962  *
3963  * 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.
3964  * 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.
3965  * 
3966  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
3967  * This convex envelop is computed using Jarvis march algorithm.
3968  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
3969  * 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)
3970  * 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.
3971  *
3972  * @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.
3973  */
3974 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
3975 {
3976   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
3977     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
3978   checkFullyDefined();
3979   const double *coords=getCoords()->getConstPointer();
3980   int nbOfCells=getNumberOfCells();
3981   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
3982   nodalConnecIndexOut->alloc(nbOfCells+1,1);
3983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
3984   int *workIndexOut=nodalConnecIndexOut->getPointer();
3985   *workIndexOut=0;
3986   const int *nodalConnecIn=_nodal_connec->getConstPointer();
3987   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
3988   std::set<INTERP_KERNEL::NormalizedCellType> types;
3989   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
3990   isChanged->alloc(0,1);
3991   for(int i=0;i<nbOfCells;i++,workIndexOut++)
3992     {
3993       int pos=nodalConnecOut->getNumberOfTuples();
3994       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
3995         isChanged->pushBackSilent(i);
3996       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
3997       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
3998     }
3999   if(isChanged->empty())
4000     return 0;
4001   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4002   _types=types;
4003   return isChanged.retn();
4004 }
4005
4006 /*!
4007  * This method is \b NOT const because it can modify 'this'.
4008  * 'this' is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4009  * @param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4010  * @param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4011  * \b 1 for translation and rotation around point of 'mesh1D'.
4012  * @return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than 'this'.  
4013  */
4014 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4015 {
4016   checkFullyDefined();
4017   mesh1D->checkFullyDefined();
4018   if(!mesh1D->isContiguous1D())
4019     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4020   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4021     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4022   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4023     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4024   if(mesh1D->getMeshDimension()!=1)
4025     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4026   bool isQuad=false;
4027   if(isPresenceOfQuadratic())
4028     {
4029       if(mesh1D->isFullyQuadratic())
4030         isQuad=true;
4031       else
4032         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4033     }
4034   zipCoords();
4035   int oldNbOfNodes=getNumberOfNodes();
4036   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4037   switch(policy)
4038     {
4039     case 0:
4040       {
4041         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4042         break;
4043       }
4044     case 1:
4045       {
4046         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4047         break;
4048       }
4049     default:
4050       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4051     }
4052   setCoords(newCoords);
4053   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4054   updateTime();
4055   return ret.retn();
4056 }
4057
4058 /*!
4059  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4060  * If it is not the case an exception will be thrown.
4061  * This method is non const because the coordinate of 'this' can be appended with some new points issued from
4062  * intersection of plane defined by ('origin','vec').
4063  * This method has one in/out parameter : 'cut3DCurve'.
4064  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4065  * if cut3DCurve[i]==-2, it means that for cell #i in 'this' nothing has been detected previously.
4066  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4067  * This method will throw an exception if 'this' contains a non linear segment.
4068  */
4069 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4070 {
4071   checkFullyDefined();
4072   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4073     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4074   int ncells=getNumberOfCells();
4075   int nnodes=getNumberOfNodes();
4076   double vec2[3],vec3[3],vec4[3];
4077   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4078   if(normm<1e-6)
4079     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4080   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4081   const int *conn=_nodal_connec->getConstPointer();
4082   const int *connI=_nodal_connec_index->getConstPointer();
4083   const double *coo=_coords->getConstPointer();
4084   std::vector<double> addCoo;
4085   for(int i=0;i<ncells;i++)
4086     {
4087       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4088         {
4089           if(cut3DCurve[i]==-2)
4090             {
4091               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4092               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];
4093               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4094               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4095               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4096                 {
4097                   const double *st2=coo+3*st;
4098                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4099                   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]));
4100                   if(pos>eps && pos<1-eps)
4101                     {
4102                       int nNode=((int)addCoo.size())/3;
4103                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4104                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4105                       cut3DCurve[i]=nnodes+nNode;
4106                     }
4107                 }
4108             }
4109         }
4110       else
4111         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4112     }
4113   if(!addCoo.empty())
4114     {
4115       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4116       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4117       coo2->alloc(newNbOfNodes,3);
4118       double *tmp=coo2->getPointer();
4119       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4120       std::copy(addCoo.begin(),addCoo.end(),tmp);
4121       DataArrayDouble::SetArrayIn(coo2,_coords);
4122     }
4123 }
4124
4125 /*!
4126  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4127  * @param mesh1D is the input 1D mesh used for translation computation.
4128  * @return newCoords new coords filled by this method. 
4129  */
4130 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4131 {
4132   int oldNbOfNodes=getNumberOfNodes();
4133   int nbOf1DCells=mesh1D->getNumberOfCells();
4134   int spaceDim=getSpaceDimension();
4135   DataArrayDouble *ret=DataArrayDouble::New();
4136   std::vector<bool> isQuads;
4137   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4138   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4139   double *retPtr=ret->getPointer();
4140   const double *coords=getCoords()->getConstPointer();
4141   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4142   std::vector<int> v;
4143   std::vector<double> c;
4144   double vec[3];
4145   v.reserve(3);
4146   c.reserve(6);
4147   for(int i=0;i<nbOf1DCells;i++)
4148     {
4149       v.resize(0);
4150       mesh1D->getNodeIdsOfCell(i,v);
4151       c.resize(0);
4152       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4153       mesh1D->getCoordinatesOfNode(v[0],c);
4154       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4155       for(int j=0;j<oldNbOfNodes;j++)
4156         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4157       if(isQuad)
4158         {
4159           c.resize(0);
4160           mesh1D->getCoordinatesOfNode(v[1],c);
4161           mesh1D->getCoordinatesOfNode(v[0],c);
4162           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4163           for(int j=0;j<oldNbOfNodes;j++)
4164             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4165         }
4166     }
4167   ret->copyStringInfoFrom(*getCoords());
4168   return ret;
4169 }
4170
4171 /*!
4172  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4173  * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4174  * @return newCoords new coords filled by this method. 
4175  */
4176 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4177 {
4178   if(mesh1D->getSpaceDimension()==2)
4179     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4180   if(mesh1D->getSpaceDimension()==3)
4181     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4182   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4183 }
4184
4185 /*!
4186  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4187  * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4188  * @return newCoords new coords filled by this method. 
4189  */
4190 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4191 {
4192   if(isQuad)
4193     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4194   int oldNbOfNodes=getNumberOfNodes();
4195   int nbOf1DCells=mesh1D->getNumberOfCells();
4196   if(nbOf1DCells<2)
4197     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4198   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4199   int nbOfLevsInVec=nbOf1DCells+1;
4200   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4201   double *retPtr=ret->getPointer();
4202   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4203   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4204   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4205   tmp->setCoords(tmp2);
4206   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4207   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4208   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4209   for(int i=1;i<nbOfLevsInVec;i++)
4210     {
4211       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4212       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4213       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4214       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4215       tmp->translate(vec);
4216       double tmp3[2],radius,alpha,alpha0;
4217       const double *p0=i+1<nbOfLevsInVec?begin:third;
4218       const double *p1=i+1<nbOfLevsInVec?end:begin;
4219       const double *p2=i+1<nbOfLevsInVec?third:end;
4220       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4221       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]);
4222       double angle=acos(cosangle/(radius*radius));
4223       tmp->rotate(end,0,angle);
4224       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4225     }
4226   return ret.retn();
4227 }
4228
4229 /*!
4230  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4231  * @param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4232  * @return newCoords new coords filled by this method. 
4233  */
4234 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4235 {
4236   if(isQuad)
4237     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4238   int oldNbOfNodes=getNumberOfNodes();
4239   int nbOf1DCells=mesh1D->getNumberOfCells();
4240   if(nbOf1DCells<2)
4241     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4242   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4243   int nbOfLevsInVec=nbOf1DCells+1;
4244   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4245   double *retPtr=ret->getPointer();
4246   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4247   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4248   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4249   tmp->setCoords(tmp2);
4250   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4251   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4252   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4253   for(int i=1;i<nbOfLevsInVec;i++)
4254     {
4255       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4256       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4257       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4258       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4259       tmp->translate(vec);
4260       double tmp3[2],radius,alpha,alpha0;
4261       const double *p0=i+1<nbOfLevsInVec?begin:third;
4262       const double *p1=i+1<nbOfLevsInVec?end:begin;
4263       const double *p2=i+1<nbOfLevsInVec?third:end;
4264       double vecPlane[3]={
4265         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4266         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4267         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4268       };
4269       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4270       if(norm>1.e-7)
4271         {
4272           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4273           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4274           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4275           double s2=norm2;
4276           double c2=cos(asin(s2));
4277           double m[3][3]={
4278             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4279             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4280             {-vec2[1]*s2, vec2[0]*s2, c2}
4281           };
4282           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]};
4283           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]};
4284           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]};
4285           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4286           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]);
4287           double angle=acos(cosangle/(radius*radius));
4288           tmp->rotate(end,vecPlane,angle);
4289           
4290         }
4291       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4292     }
4293   return ret.retn();
4294 }
4295
4296 /*!
4297  * This method is private because not easy to use for end user. This method is const contrary to
4298  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4299  * the coords sorted slice by slice.
4300  * @param isQuad specifies presence of quadratic cells.
4301  */
4302 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4303 {
4304   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4305   int nbOf2DCells=getNumberOfCells();
4306   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4307   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4308   const int *conn=_nodal_connec->getConstPointer();
4309   const int *connI=_nodal_connec_index->getConstPointer();
4310   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4311   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4312   newConnI->alloc(nbOf3DCells+1,1);
4313   int *newConnIPtr=newConnI->getPointer();
4314   *newConnIPtr++=0;
4315   std::vector<int> newc;
4316   for(int j=0;j<nbOf2DCells;j++)
4317     {
4318       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4319       *newConnIPtr++=(int)newc.size();
4320     }
4321   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4322   int *newConnPtr=newConn->getPointer();
4323   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4324   newConnIPtr=newConnI->getPointer();
4325   for(int iz=0;iz<nbOf1DCells;iz++)
4326     {
4327       if(iz!=0)
4328         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4329       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4330         {
4331           int icell=(int)(iter-newc.begin());
4332           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4333             {
4334               if(*iter!=-1)
4335                 *newConnPtr=(*iter)+iz*deltaPerLev;
4336               else
4337                 *newConnPtr=-1;
4338             }
4339           else
4340             *newConnPtr=(*iter);
4341         }
4342     }
4343   ret->setConnectivity(newConn,newConnI,true);
4344   ret->setCoords(getCoords());
4345   return ret;
4346 }
4347
4348 /*!
4349  * This method returns if 'this' is constituted by only quadratic cells.
4350  */
4351 bool MEDCouplingUMesh::isFullyQuadratic() const
4352 {
4353   checkFullyDefined();
4354   bool ret=true;
4355   int nbOfCells=getNumberOfCells();
4356   for(int i=0;i<nbOfCells && ret;i++)
4357     {
4358       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4359       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4360       ret=cm.isQuadratic();
4361     }
4362   return ret;
4363 }
4364
4365 /*!
4366  * This method returns if there is at least one quadratic cell.
4367  */
4368 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4369 {
4370   checkFullyDefined();
4371   bool ret=false;
4372   int nbOfCells=getNumberOfCells();
4373   for(int i=0;i<nbOfCells && !ret;i++)
4374     {
4375       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4376       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4377       ret=cm.isQuadratic();
4378     }
4379   return ret;
4380 }
4381
4382 /*!
4383  * This method convert quadratic cells to linear cells if any was found.
4384  * If no such cells exists 'this' remains unchanged.
4385  */
4386 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4387 {
4388   checkFullyDefined();
4389   int nbOfCells=getNumberOfCells();
4390   int delta=0;
4391   for(int i=0;i<nbOfCells;i++)
4392     {
4393       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4394       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4395       if(cm.isQuadratic())
4396         {
4397           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4398           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4399           delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4400         }
4401     }
4402   if(delta==0)
4403     return ;
4404   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4405   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4406   newConn->alloc(getMeshLength()-delta,1);
4407   newConnI->alloc(nbOfCells+1,1);
4408   const int *icptr=_nodal_connec->getConstPointer();
4409   const int *iciptr=_nodal_connec_index->getConstPointer();
4410   int *ocptr=newConn->getPointer();
4411   int *ociptr=newConnI->getPointer();
4412   *ociptr=0;
4413   _types.clear();
4414   for(int i=0;i<nbOfCells;i++,ociptr++)
4415     {
4416       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4417       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4418       if(!cm.isQuadratic())
4419         {
4420           _types.insert(type);
4421           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4422           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4423         }
4424       else
4425         {
4426           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4427           _types.insert(typel);
4428           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4429           int newNbOfNodes=cml.getNumberOfNodes();
4430           *ocptr++=(int)typel;
4431           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4432           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4433         }
4434     }
4435   setConnectivity(newConn,newConnI,false);
4436 }
4437
4438 /*!
4439  * This method converts all linear cell in \a this to quadratic one.
4440  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4441  * 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)
4442  * 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.
4443  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4444  * end of the existing coordinates.
4445  * 
4446  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4447  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4448  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4449  * 
4450  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4451  *
4452  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4453  */
4454 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4455 {
4456   DataArrayInt *conn=0,*connI=0;
4457   DataArrayDouble *coords=0;
4458   std::set<INTERP_KERNEL::NormalizedCellType> types;
4459   checkFullyDefined();
4460   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4461   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4462   int meshDim=getMeshDimension();
4463   switch(conversionType)
4464     {
4465     case 0:
4466       switch(meshDim)
4467         {
4468         case 1:
4469           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4470           connSafe=conn; connISafe=connI; coordsSafe=coords;
4471           break;
4472         case 2:
4473           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4474           connSafe=conn; connISafe=connI; coordsSafe=coords;
4475           break;
4476         case 3:
4477           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4478           connSafe=conn; connISafe=connI; coordsSafe=coords;
4479           break;
4480         default:
4481           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4482         }
4483       break;
4484     case 1:
4485       {
4486         switch(meshDim)
4487         {
4488         case 1:
4489           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4490           connSafe=conn; connISafe=connI; coordsSafe=coords;
4491           break;
4492         case 2:
4493           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4494           connSafe=conn; connISafe=connI; coordsSafe=coords;
4495           break;
4496         case 3:
4497           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4498           connSafe=conn; connISafe=connI; coordsSafe=coords;
4499           break;
4500         default:
4501           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4502         }
4503         break;
4504       }
4505     default:
4506       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4507     }
4508   setConnectivity(connSafe,connISafe,false);
4509   _types=types;
4510   setCoords(coordsSafe);
4511   return ret.retn();
4512 }
4513
4514 /*!
4515  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4516  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4517  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4518  */
4519 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4520 {
4521   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4522   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4523   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4524   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4525   int nbOfCells=getNumberOfCells();
4526   int nbOfNodes=getNumberOfNodes();
4527   const int *cPtr=_nodal_connec->getConstPointer();
4528   const int *icPtr=_nodal_connec_index->getConstPointer();
4529   int lastVal=0,offset=nbOfNodes;
4530   for(int i=0;i<nbOfCells;i++,icPtr++)
4531     {
4532       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4533       if(type==INTERP_KERNEL::NORM_SEG2)
4534         {
4535           types.insert(INTERP_KERNEL::NORM_SEG3);
4536           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4537           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4538           newConn->pushBackSilent(offset++);
4539           lastVal+=4;
4540           newConnI->pushBackSilent(lastVal);
4541           ret->pushBackSilent(i);
4542         }
4543       else
4544         {
4545           types.insert(type);
4546           lastVal+=(icPtr[1]-icPtr[0]);
4547           newConnI->pushBackSilent(lastVal);
4548           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4549         }
4550     }
4551   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4552   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4553   return ret.retn();
4554 }
4555
4556 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 throw(INTERP_KERNEL::Exception)
4557 {
4558   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4559   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4560   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4561   //
4562   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4563   DataArrayInt *conn1D=0,*conn1DI=0;
4564   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4565   DataArrayDouble *coordsTmp=0;
4566   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4567   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4568   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4569   const int *c1DPtr=conn1D->begin();
4570   const int *c1DIPtr=conn1DI->begin();
4571   int nbOfCells=getNumberOfCells();
4572   const int *cPtr=_nodal_connec->getConstPointer();
4573   const int *icPtr=_nodal_connec_index->getConstPointer();
4574   int lastVal=0;
4575   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4576     {
4577       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4578       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4579       if(!cm.isQuadratic())
4580         {
4581           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4582           types.insert(typ2); newConn->pushBackSilent(typ2);
4583           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4584           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4585             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4586           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4587           newConnI->pushBackSilent(lastVal);
4588           ret->pushBackSilent(i);
4589         }
4590       else
4591         {
4592           types.insert(typ);
4593           lastVal+=(icPtr[1]-icPtr[0]);
4594           newConnI->pushBackSilent(lastVal);
4595           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4596         }
4597     }
4598   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4599   return ret.retn();
4600 }
4601
4602 /*!
4603  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4604  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4605  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4606  */
4607 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4608 {
4609   
4610   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4611   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4612   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4613 }
4614
4615 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4616 {
4617   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4618   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4619   //
4620   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4621   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4622   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4623   //
4624   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4625   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4626   DataArrayInt *conn1D=0,*conn1DI=0;
4627   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4628   DataArrayDouble *coordsTmp=0;
4629   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4630   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4631   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4632   const int *c1DPtr=conn1D->begin();
4633   const int *c1DIPtr=conn1DI->begin();
4634   int nbOfCells=getNumberOfCells();
4635   const int *cPtr=_nodal_connec->getConstPointer();
4636   const int *icPtr=_nodal_connec_index->getConstPointer();
4637   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4638   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4639     {
4640       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4641       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4642       if(!cm.isQuadratic())
4643         {
4644           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4645           types.insert(typ2); newConn->pushBackSilent(typ2);
4646           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4647           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4648             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4649           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
4650           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
4651           newConnI->pushBackSilent(lastVal);
4652           ret->pushBackSilent(i);
4653         }
4654       else
4655         {
4656           types.insert(typ);
4657           lastVal+=(icPtr[1]-icPtr[0]);
4658           newConnI->pushBackSilent(lastVal);
4659           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4660         }
4661     }
4662   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4663   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
4664   return ret.retn();
4665 }
4666
4667 /*!
4668  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4669  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4670  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4671  */
4672 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4673 {
4674   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4675   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4676   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4677 }
4678
4679 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4680 {
4681   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4682   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
4683   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
4684   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
4685   //
4686   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4687   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4688   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
4689   //
4690   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4691   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
4692   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
4693   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
4694   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
4695   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
4696   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4697   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4698   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
4699   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
4700   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
4701   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
4702   int nbOfCells=getNumberOfCells();
4703   const int *cPtr=_nodal_connec->getConstPointer();
4704   const int *icPtr=_nodal_connec_index->getConstPointer();
4705   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4706   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
4707     {
4708       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4709       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4710       if(!cm.isQuadratic())
4711         {
4712           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4713           if(typ2==INTERP_KERNEL::NORM_ERROR)
4714             {
4715               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
4716               throw INTERP_KERNEL::Exception(oss.str().c_str());
4717             }
4718           types.insert(typ2); newConn->pushBackSilent(typ2);
4719           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4720           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4721             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4722           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
4723             {
4724               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
4725               int tmpPos=newConn->getNumberOfTuples();
4726               newConn->pushBackSilent(nodeId2);
4727               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
4728             }
4729           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
4730           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
4731           newConnI->pushBackSilent(lastVal);
4732           ret->pushBackSilent(i);
4733         }
4734       else
4735         {
4736           types.insert(typ);
4737           lastVal+=(icPtr[1]-icPtr[0]);
4738           newConnI->pushBackSilent(lastVal);
4739           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4740         }
4741     }
4742   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
4743   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
4744   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
4745   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4746   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
4747   int *c=newConn->getPointer();
4748   const int *cI(newConnI->begin());
4749   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
4750     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
4751   offset=coordsTmp2Safe->getNumberOfTuples();
4752   for(const int *elt=ret->begin();elt!=ret->end();elt++)
4753     c[cI[(*elt)+1]-1]+=offset;
4754   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
4755   return ret.retn();
4756 }
4757
4758 /*!
4759  * This method tessallates 'this' so that the number of cells remains the same.
4760  * This method works only for meshes with spaceDim equal to 2 and meshDim equal to 2.
4761  * If no cells are quadratic in 'this' (INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ) this method will remain unchanged.
4762  * 
4763  * \b WARNING this method can lead to a uge amount of nodes if eps is very low.
4764  * @param eps specifies the maximal angle (in radian) between 2 subedges of polylinized edge constituting the input polygon.
4765  */
4766 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
4767 {
4768   checkFullyDefined();
4769   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
4770     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
4771   double epsa=fabs(eps);
4772   if(epsa<std::numeric_limits<double>::min())
4773     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 !");
4774   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
4775   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
4776   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
4777   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
4778   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
4779   revDesc1=0; revDescIndx1=0;
4780   mDesc->tessellate2DCurve(eps);
4781   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
4782   setCoords(mDesc->getCoords());
4783 }
4784
4785 /*!
4786  * This method tessallates 'this' so that the number of cells remains the same.
4787  * This method works only for meshes with spaceDim equal to 2 and meshDim equal to 1.
4788  * If no cells are quadratic in 'this' (INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ) this method will remain unchanged.
4789  * 
4790  * \b WARNING this method can lead to a uge amount of nodes if eps is very low.
4791  * @param eps specifies the maximal angle (in radian) between 2 subedges of polylinized edge constituting the input polygon.
4792  */
4793 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
4794 {
4795   checkFullyDefined();
4796   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
4797     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
4798   double epsa=fabs(eps);
4799   if(epsa<std::numeric_limits<double>::min())
4800     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 !");
4801   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
4802   int nbCells=getNumberOfCells();
4803   int nbNodes=getNumberOfNodes();
4804   const int *conn=_nodal_connec->getConstPointer();
4805   const int *connI=_nodal_connec_index->getConstPointer();
4806   const double *coords=_coords->getConstPointer();
4807   std::vector<double> addCoo;
4808   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
4809   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
4810   newConnI->alloc(nbCells+1,1);
4811   int *newConnIPtr=newConnI->getPointer();
4812   *newConnIPtr=0;
4813   int tmp1[3];
4814   INTERP_KERNEL::Node *tmp2[3];
4815   std::set<INTERP_KERNEL::NormalizedCellType> types;
4816   for(int i=0;i<nbCells;i++,newConnIPtr++)
4817     {
4818       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4819       if(cm.isQuadratic())
4820         {//assert(connI[i+1]-connI[i]-1==3)
4821           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
4822           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
4823           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
4824           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
4825           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
4826           if(eac)
4827             {
4828               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
4829               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
4830               delete eac;
4831               newConnIPtr[1]=(int)newConn.size();
4832             }
4833           else
4834             {
4835               types.insert(INTERP_KERNEL::NORM_SEG2);
4836               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
4837               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
4838               newConnIPtr[1]=newConnIPtr[0]+3;
4839             }
4840         }
4841       else
4842         {
4843           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4844           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
4845           newConnIPtr[1]=newConnIPtr[0]+3;
4846         }
4847     }
4848   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
4849     return ;
4850   _types=types;
4851   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
4852   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
4853   newConnArr->alloc((int)newConn.size(),1);
4854   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
4855   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
4856   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
4857   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
4858   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
4859   std::copy(addCoo.begin(),addCoo.end(),work);
4860   DataArrayDouble::SetArrayIn(newCoords,_coords);
4861   updateTime();
4862 }
4863
4864 /*!
4865  * This methods modify this by converting each cells into simplex cell, that is too say triangle for meshdim==2 or tetra for meshdim==3.
4866  * This cut into simplex is performed following the parameter \a policy. This method so typically increases the number of cells of \a this.
4867  * This method \b keeps the number of nodes \b unchanged. That's why the splitting policy in 3D INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
4868  * This method returns new2old newly allocated array that specifies a each cell of \a this after the call what was its id it comes.
4869  * 
4870  * The semantic of \a policy parameter :
4871  * - 1 only QUAD4. For QUAD4 the cut is done along 0-2 diagonal for QUAD4
4872  * - 2 only QUAD4. For QUAD4 the cut is done along 1-3 diagonal for QUAD4
4873  * - PLANAR_FACE_5 only HEXA8. All HEXA8 are split into 5 TETRA4
4874  * - PLANAR_FACE_6 only HEXA8. All HEXA8 are split into 6 TETRA4
4875  */
4876 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
4877 {
4878   switch(policy)
4879     {
4880     case 0:
4881       return simplexizePol0();
4882     case 1:
4883       return simplexizePol1();
4884     case (int) INTERP_KERNEL::PLANAR_FACE_5:
4885       return simplexizePlanarFace5();
4886     case (int) INTERP_KERNEL::PLANAR_FACE_6:
4887       return simplexizePlanarFace6();
4888     default:
4889       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)");
4890     }
4891 }
4892
4893 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
4894 {
4895   checkFullyDefined();
4896   if(getMeshDimension()<1)
4897     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim >= 1 !");
4898   int nbCells=getNumberOfCells();
4899   const int *conn=_nodal_connec->getConstPointer();
4900   const int *connI=_nodal_connec_index->getConstPointer();
4901   for(int i=0;i<nbCells;i++)
4902     {
4903       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
4904       if(!cm.isSimplex())
4905         return false;
4906     }
4907   return true;
4908 }
4909
4910 /*!
4911  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4912  */
4913 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
4914 {
4915   checkConnectivityFullyDefined();
4916   if(getMeshDimension()!=2)
4917     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
4918   int nbOfCells=getNumberOfCells();
4919   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
4920   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
4921   ret->alloc(nbOfCells+nbOfCutCells,1);
4922   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
4923   int *retPt=ret->getPointer();
4924   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4925   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4926   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
4927   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
4928   int *pt=newConn->getPointer();
4929   int *ptI=newConnI->getPointer();
4930   ptI[0]=0;
4931   const int *oldc=_nodal_connec->getConstPointer();
4932   const int *ci=_nodal_connec_index->getConstPointer();
4933   for(int i=0;i<nbOfCells;i++,ci++)
4934     {
4935       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
4936         {
4937           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
4938                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
4939           pt=std::copy(tmp,tmp+8,pt);
4940           ptI[1]=ptI[0]+4;
4941           ptI[2]=ptI[0]+8;
4942           *retPt++=i;
4943           *retPt++=i;
4944           ptI+=2;
4945         }
4946       else
4947         {
4948           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
4949           ptI[1]=ptI[0]+ci[1]-ci[0];
4950           ptI++;
4951           *retPt++=i;
4952         }
4953     }
4954   _nodal_connec->decrRef();
4955   _nodal_connec=newConn.retn();
4956   _nodal_connec_index->decrRef();
4957   _nodal_connec_index=newConnI.retn();
4958   computeTypes();
4959   updateTime();
4960   return ret.retn();
4961 }
4962
4963 /*!
4964  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
4965  */
4966 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
4967 {
4968   checkConnectivityFullyDefined();
4969   if(getMeshDimension()!=2)
4970     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
4971   int nbOfCells=getNumberOfCells();
4972   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
4973   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
4974   ret->alloc(nbOfCells+nbOfCutCells,1);
4975   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
4976   int *retPt=ret->getPointer();
4977   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4978   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4979   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
4980   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
4981   int *pt=newConn->getPointer();
4982   int *ptI=newConnI->getPointer();
4983   ptI[0]=0;
4984   const int *oldc=_nodal_connec->getConstPointer();
4985   const int *ci=_nodal_connec_index->getConstPointer();
4986   for(int i=0;i<nbOfCells;i++,ci++)
4987     {
4988       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
4989         {
4990           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
4991                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
4992           pt=std::copy(tmp,tmp+8,pt);
4993           ptI[1]=ptI[0]+4;
4994           ptI[2]=ptI[0]+8;
4995           *retPt++=i;
4996           *retPt++=i;
4997           ptI+=2;
4998         }
4999       else
5000         {
5001           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5002           ptI[1]=ptI[0]+ci[1]-ci[0];
5003           ptI++;
5004           *retPt++=i;
5005         }
5006     }
5007   _nodal_connec->decrRef();
5008   _nodal_connec=newConn.retn();
5009   _nodal_connec_index->decrRef();
5010   _nodal_connec_index=newConnI.retn();
5011   computeTypes();
5012   updateTime();
5013   return ret.retn();
5014 }
5015
5016 /*!
5017  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5018  */
5019 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5020 {
5021   checkConnectivityFullyDefined();
5022   if(getMeshDimension()!=3)
5023     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5024   int nbOfCells=getNumberOfCells();
5025   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5026   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5027   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5028   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5029   int *retPt=ret->getPointer();
5030   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5031   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5032   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5033   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5034   int *pt=newConn->getPointer();
5035   int *ptI=newConnI->getPointer();
5036   ptI[0]=0;
5037   const int *oldc=_nodal_connec->getConstPointer();
5038   const int *ci=_nodal_connec_index->getConstPointer();
5039   for(int i=0;i<nbOfCells;i++,ci++)
5040     {
5041       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5042         {
5043           for(int j=0;j<5;j++,pt+=5,ptI++)
5044             {
5045               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5046               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];
5047               *retPt++=i;
5048               ptI[1]=ptI[0]+5;
5049             }
5050         }
5051       else
5052         {
5053           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5054           ptI[1]=ptI[0]+ci[1]-ci[0];
5055           ptI++;
5056           *retPt++=i;
5057         }
5058     }
5059   _nodal_connec->decrRef();
5060   _nodal_connec=newConn.retn();
5061   _nodal_connec_index->decrRef();
5062   _nodal_connec_index=newConnI.retn();
5063   computeTypes();
5064   updateTime();
5065   return ret.retn();
5066 }
5067
5068 /*!
5069  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5070  */
5071 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5072 {
5073   checkConnectivityFullyDefined();
5074   if(getMeshDimension()!=3)
5075     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5076   int nbOfCells=getNumberOfCells();
5077   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5078   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5079   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5080   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5081   int *retPt=ret->getPointer();
5082   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5083   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5084   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5085   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5086   int *pt=newConn->getPointer();
5087   int *ptI=newConnI->getPointer();
5088   ptI[0]=0;
5089   const int *oldc=_nodal_connec->getConstPointer();
5090   const int *ci=_nodal_connec_index->getConstPointer();
5091   for(int i=0;i<nbOfCells;i++,ci++)
5092     {
5093       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5094         {
5095           for(int j=0;j<6;j++,pt+=5,ptI++)
5096             {
5097               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5098               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];
5099               *retPt++=i;
5100               ptI[1]=ptI[0]+5;
5101             }
5102         }
5103       else
5104         {
5105           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5106           ptI[1]=ptI[0]+ci[1]-ci[0];
5107           ptI++;
5108           *retPt++=i;
5109         }
5110     }
5111   _nodal_connec->decrRef();
5112   _nodal_connec=newConn.retn();
5113   _nodal_connec_index->decrRef();
5114   _nodal_connec_index=newConnI.retn();
5115   computeTypes();
5116   updateTime();
5117   return ret.retn();
5118 }
5119
5120 /*!
5121  * This private method is used to subdivide edges of a mesh with meshdim==2. If 'this' has no a meshdim equal to 2 an exception will be thrown.
5122  * This method completly ignore coordinates.
5123  * @param nodeSubdived is the nodal connectivity of subdivision of edges
5124  * @param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5125  * @param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5126  * @param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5127  */
5128 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5129 {
5130   checkFullyDefined();
5131   if(getMeshDimension()!=2)
5132     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5133   int nbOfCells=getNumberOfCells();
5134   int *connI=_nodal_connec_index->getPointer();
5135   int newConnLgth=0;
5136   for(int i=0;i<nbOfCells;i++,connI++)
5137     {
5138       int offset=descIndex[i];
5139       int nbOfEdges=descIndex[i+1]-offset;
5140       //
5141       bool ddirect=desc[offset+nbOfEdges-1]>0;
5142       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5143       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5144       for(int j=0;j<nbOfEdges;j++)
5145         {
5146           bool direct=desc[offset+j]>0;
5147           int edgeId=std::abs(desc[offset+j])-1;
5148           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5149             {
5150               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5151               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5152               int ref2=direct?id1:id2;
5153               if(ref==ref2)
5154                 {
5155                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5156                   newConnLgth+=nbOfSubNodes-1;
5157                   ref=direct?id2:id1;
5158                 }
5159               else
5160                 {
5161                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5162                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5163                 }
5164             }
5165           else
5166             {
5167               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5168             }
5169         }
5170       newConnLgth++;//+1 is for cell type
5171       connI[1]=newConnLgth;
5172     }
5173   //
5174   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5175   newConn->alloc(newConnLgth,1);
5176   int *work=newConn->getPointer();
5177   for(int i=0;i<nbOfCells;i++)
5178     {
5179       *work++=INTERP_KERNEL::NORM_POLYGON;
5180       int offset=descIndex[i];
5181       int nbOfEdges=descIndex[i+1]-offset;
5182       for(int j=0;j<nbOfEdges;j++)
5183         {
5184           bool direct=desc[offset+j]>0;
5185           int edgeId=std::abs(desc[offset+j])-1;
5186           if(direct)
5187             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5188           else
5189             {
5190               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5191               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5192               work=std::copy(it,it+nbOfSubNodes-1,work);
5193             }
5194         }
5195     }
5196   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5197   _types.clear();
5198   if(nbOfCells>0)
5199     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5200 }
5201
5202 /*!
5203  * This method converts all degenerated cells to simpler cells. For example a NORM_QUAD4 cell consituted from 2 same node id in its
5204  * nodal connectivity will be transform to a NORM_TRI3 cell.
5205  * This method works \b only \b on \b linear cells.
5206  * This method works on nodes ids, that is to say a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes
5207  * method could be useful before calling this method in case of presence of several pair of nodes located on same position.
5208  * This method throws an exception if 'this' is not fully defined (connectivity).
5209  * This method throws an exception too if a "too" degenerated cell is detected. For example a NORM_TRI3 with 3 times the same node id.
5210  */
5211 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5212 {
5213   checkFullyDefined();
5214   if(getMeshDimension()<=1)
5215     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5216   int nbOfCells=getNumberOfCells();
5217   if(nbOfCells<1)
5218     return ;
5219   int initMeshLgth=getMeshLength();
5220   int *conn=_nodal_connec->getPointer();
5221   int *index=_nodal_connec_index->getPointer();
5222   int posOfCurCell=0;
5223   int newPos=0;
5224   int lgthOfCurCell;
5225   for(int i=0;i<nbOfCells;i++)
5226     {
5227       lgthOfCurCell=index[i+1]-posOfCurCell;
5228       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5229       int newLgth;
5230       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5231                                                                                                      conn+newPos+1,newLgth);
5232       conn[newPos]=newType;
5233       newPos+=newLgth+1;
5234       posOfCurCell=index[i+1];
5235       index[i+1]=newPos;
5236     }
5237   if(newPos!=initMeshLgth)
5238     _nodal_connec->reAlloc(newPos);
5239   computeTypes();
5240 }
5241
5242 /*!
5243  * This method checks that all or only polygons (depending 'polyOnly' parameter) 2D cells are correctly oriented relative to 'vec' vector.
5244  * The 'vec' vector has to have a non nul norm.
5245  * If not 'cells' parameter will be appended with cellIds of incorrect cells.
5246  * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
5247  */
5248 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5249 {
5250   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5251     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5252   int nbOfCells=getNumberOfCells();
5253   const int *conn=_nodal_connec->getConstPointer();
5254   const int *connI=_nodal_connec_index->getConstPointer();
5255   const double *coordsPtr=_coords->getConstPointer();
5256   for(int i=0;i<nbOfCells;i++)
5257     {
5258       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5259       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5260         {
5261           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5262           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5263             cells.push_back(i);
5264         }
5265     }
5266 }
5267
5268 /*!
5269  * This method orient correctly (if needed) all or only polygons (depending 'polyOnly' parameter)  2D cells are correctly oriented relative to 'vec' vector.
5270  * The 'vec' vector has to have a non nul norm.
5271  * @throw when 'this' is not a mesh with meshdim==2 and spacedim==3
5272  */
5273 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5274 {
5275   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5276     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5277   int nbOfCells=getNumberOfCells();
5278   int *conn=_nodal_connec->getPointer();
5279   const int *connI=_nodal_connec_index->getConstPointer();
5280   const double *coordsPtr=_coords->getConstPointer();
5281   bool isModified=false;
5282   for(int i=0;i<nbOfCells;i++)
5283     {
5284       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5285       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5286         {
5287           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5288           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5289             {
5290               isModified=true;
5291               std::vector<int> tmp(connI[i+1]-connI[i]-2);
5292               std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5293               std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5294             }
5295         }
5296     }
5297   if(isModified)
5298     _nodal_connec->declareAsNew();
5299   updateTime();
5300 }
5301
5302 /*!
5303  * This method checks that all polyhedrons cells have correctly oriented faces.
5304  * If not, 'cells' parameter will be appended with cellIds of incorrect cells.
5305  * @throw when 'this' is not a mesh with meshdim==3 and spacedim==3
5306  */
5307 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5308 {
5309   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5310     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5311   int nbOfCells=getNumberOfCells();
5312   const int *conn=_nodal_connec->getConstPointer();
5313   const int *connI=_nodal_connec_index->getConstPointer();
5314   const double *coordsPtr=_coords->getConstPointer();
5315   for(int i=0;i<nbOfCells;i++)
5316     {
5317       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5318       if(type==INTERP_KERNEL::NORM_POLYHED)
5319         {
5320           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5321             cells.push_back(i);
5322         }
5323     }
5324 }
5325
5326 /*!
5327  * This method tries to orient correctly polhedrons cells.
5328  * 
5329  * \throw when 'this' is not a mesh with meshdim==3 and spacedim==3. An exception is also thrown when the attempt of reparation fails.
5330  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5331  */
5332 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5333 {
5334   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5335     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5336   int nbOfCells=getNumberOfCells();
5337   int *conn=_nodal_connec->getPointer();
5338   const int *connI=_nodal_connec_index->getConstPointer();
5339   const double *coordsPtr=_coords->getConstPointer();
5340   for(int i=0;i<nbOfCells;i++)
5341     {
5342       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5343       if(type==INTERP_KERNEL::NORM_POLYHED)
5344         {
5345           try
5346             {
5347               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5348                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5349             }
5350           catch(INTERP_KERNEL::Exception& e)
5351             {
5352               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5353               throw INTERP_KERNEL::Exception(oss.str().c_str());
5354             }
5355         }
5356     }
5357   updateTime();
5358 }
5359
5360 /*!
5361  * This method is expected to be applied on a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
5362  * This method analyzes only linear extruded 3D cells (NORM_HEXA8,NORM_PENTA6,NORM_HEXGP12...)
5363  * If some extruded cells does not fulfill the MED norm for extruded cells (first face of 3D cell should be oriented to the exterior of the 3D cell).
5364  * Some viewers are very careful of that (SMESH), but ParaVis ignore that.
5365  *
5366  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5367  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5368  */
5369 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5370 {
5371   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5372   if(getMeshDimension()!=3)
5373     throw INTERP_KERNEL::Exception(msg);
5374   int spaceDim=getSpaceDimension();
5375   if(spaceDim!=3)
5376     throw INTERP_KERNEL::Exception(msg);
5377   //
5378   int nbOfCells=getNumberOfCells();
5379   int *conn=_nodal_connec->getPointer();
5380   const int *connI=_nodal_connec_index->getConstPointer();
5381   const double *coo=getCoords()->getConstPointer();
5382   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5383   for(int i=0;i<nbOfCells;i++)
5384     {
5385       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5386       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5387         {
5388           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5389             {
5390               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5391               cells->pushBackSilent(i);
5392             }
5393         }
5394     }
5395   return cells.retn();
5396 }
5397
5398 /*!
5399  * This method is a faster method to correct orientation of all 3D cells in \a this.
5400  * 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.
5401  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5402  * 
5403  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5404  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5405  */
5406 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5407 {
5408   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5409     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5410   int nbOfCells=getNumberOfCells();
5411   int *conn=_nodal_connec->getPointer();
5412   const int *connI=_nodal_connec_index->getConstPointer();
5413   const double *coordsPtr=_coords->getConstPointer();
5414   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5415   for(int i=0;i<nbOfCells;i++)
5416     {
5417       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5418       switch(type)
5419         {
5420         case INTERP_KERNEL::NORM_TETRA4:
5421           {
5422             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5423               {
5424                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5425                 ret->pushBackSilent(i);
5426               }
5427             break;
5428           }
5429         case INTERP_KERNEL::NORM_PYRA5:
5430           {
5431             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5432               {
5433                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5434                 ret->pushBackSilent(i);
5435               }
5436             break;
5437           }
5438         case INTERP_KERNEL::NORM_PENTA6:
5439         case INTERP_KERNEL::NORM_HEXA8:
5440         case INTERP_KERNEL::NORM_HEXGP12:
5441           {
5442             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5443               {
5444                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5445                 ret->pushBackSilent(i);
5446               }
5447             break;
5448           }
5449         case INTERP_KERNEL::NORM_POLYHED:
5450           {
5451             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5452               {
5453                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5454                 ret->pushBackSilent(i);
5455               }
5456             break;
5457           }
5458         default:
5459           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 !");
5460         }
5461     }
5462   updateTime();
5463   return ret.retn();
5464 }
5465
5466 /*!
5467  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5468  * If it is not the case an exception will be thrown.
5469  * This method is fast because the first cell of 'this' is used to compute the plane.
5470  * @param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5471  * @param pos output of size at least 3 used to store a point owned of searched plane.
5472  */
5473 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5474 {
5475   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5476     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5477   const int *conn=_nodal_connec->getConstPointer();
5478   const int *connI=_nodal_connec_index->getConstPointer();
5479   const double *coordsPtr=_coords->getConstPointer();
5480   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5481   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5482 }
5483
5484 /*!
5485  * The returned newly created field has to be managed by the caller.
5486  * This method returns a field on cell with no time lying on 'this'. The meshdimension and spacedimension of this are expected to be both in [2,3]. If not an exception will be thrown.
5487  * This method for the moment only deals with NORM_TRI3, NORM_QUAD4 and NORM_TETRA4 geometric types.
5488  * If a cell has an another type an exception will be thrown.
5489  */
5490 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5491 {
5492   checkCoherency();
5493   int spaceDim=getSpaceDimension();
5494   int meshDim=getMeshDimension();
5495   if(spaceDim!=2 && spaceDim!=3)
5496     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5497   if(meshDim!=2 && meshDim!=3)
5498     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5499   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5500   ret->setMesh(this);
5501   int nbOfCells=getNumberOfCells();
5502   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5503   arr->alloc(nbOfCells,1);
5504   double *pt=arr->getPointer();
5505   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5506   const int *conn=_nodal_connec->getConstPointer();
5507   const int *connI=_nodal_connec_index->getConstPointer();
5508   const double *coo=_coords->getConstPointer();
5509   double tmp[12];
5510   for(int i=0;i<nbOfCells;i++,pt++)
5511     {
5512       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5513       switch(t)
5514         {
5515           case INTERP_KERNEL::NORM_TRI3:
5516             {
5517               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5518               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5519               break;
5520             }
5521           case INTERP_KERNEL::NORM_QUAD4:
5522             {
5523               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5524               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5525               break;
5526             }
5527           case INTERP_KERNEL::NORM_TETRA4:
5528             {
5529               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5530               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5531               break;
5532             }
5533         default:
5534           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5535         }
5536       conn+=connI[i+1]-connI[i];
5537     }
5538   ret->setName("EdgeRatio");
5539   ret->synchronizeTimeWithSupport();
5540   return ret.retn();
5541 }
5542
5543 /*!
5544  * The returned newly created field has to be managed by the caller.
5545  * This method returns a field on cell with no time lying on 'this'. The meshdimension and spacedimension of this are expected to be both in [2,3]. If not an exception will be thrown.
5546  * This method for the moment only deals with NORM_TRI3, NORM_QUAD4 and NORM_TETRA4 geometric types.
5547  * If a cell has an another type an exception will be thrown.
5548  */
5549 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
5550 {
5551   checkCoherency();
5552   int spaceDim=getSpaceDimension();
5553   int meshDim=getMeshDimension();
5554   if(spaceDim!=2 && spaceDim!=3)
5555     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5556   if(meshDim!=2 && meshDim!=3)
5557     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5558   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5559   ret->setMesh(this);
5560   int nbOfCells=getNumberOfCells();
5561   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5562   arr->alloc(nbOfCells,1);
5563   double *pt=arr->getPointer();
5564   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5565   const int *conn=_nodal_connec->getConstPointer();
5566   const int *connI=_nodal_connec_index->getConstPointer();
5567   const double *coo=_coords->getConstPointer();
5568   double tmp[12];
5569   for(int i=0;i<nbOfCells;i++,pt++)
5570     {
5571       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5572       switch(t)
5573         {
5574           case INTERP_KERNEL::NORM_TRI3:
5575             {
5576               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5577               *pt=INTERP_KERNEL::triAspectRatio(tmp);
5578               break;
5579             }
5580           case INTERP_KERNEL::NORM_QUAD4:
5581             {
5582               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5583               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
5584               break;
5585             }
5586           case INTERP_KERNEL::NORM_TETRA4:
5587             {
5588               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5589               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
5590               break;
5591             }
5592         default:
5593           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5594         }
5595       conn+=connI[i+1]-connI[i];
5596     }
5597   ret->setName("AspectRatio");
5598   ret->synchronizeTimeWithSupport();
5599   return ret.retn();
5600 }
5601
5602 /*!
5603  * The returned newly created field has to be managed by the caller.
5604  * This method returns a field on cell with no time lying on 'this'. The meshdimension must be equal to 2 and the spacedimension must be equal to 3. If not an exception will be thrown.
5605  * This method for the moment only deals with NORM_QUAD4 geometric type.
5606  * If a cell has an another type an exception will be thrown.
5607  */
5608 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
5609 {
5610   checkCoherency();
5611   int spaceDim=getSpaceDimension();
5612   int meshDim=getMeshDimension();
5613   if(spaceDim!=3)
5614     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
5615   if(meshDim!=2)
5616     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
5617   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5618   ret->setMesh(this);
5619   int nbOfCells=getNumberOfCells();
5620   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5621   arr->alloc(nbOfCells,1);
5622   double *pt=arr->getPointer();
5623   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5624   const int *conn=_nodal_connec->getConstPointer();
5625   const int *connI=_nodal_connec_index->getConstPointer();
5626   const double *coo=_coords->getConstPointer();
5627   double tmp[12];
5628   for(int i=0;i<nbOfCells;i++,pt++)
5629     {
5630       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5631       switch(t)
5632         {
5633           case INTERP_KERNEL::NORM_QUAD4:
5634             {
5635               FillInCompact3DMode(3,4,conn+1,coo,tmp);
5636               *pt=INTERP_KERNEL::quadWarp(tmp);
5637               break;
5638             }
5639         default:
5640           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
5641         }
5642       conn+=connI[i+1]-connI[i];
5643     }
5644   ret->setName("Warp");
5645   ret->synchronizeTimeWithSupport();
5646   return ret.retn();
5647 }
5648
5649 /*!
5650  * The returned newly created field has to be managed by the caller.
5651  * This method returns a field on cell with no time lying on 'this'. The meshdimension must be equal to 2 and the spacedimension must be equal to 3. If not an exception will be thrown.
5652  * This method for the moment only deals with NORM_QUAD4 geometric type.
5653  * If a cell has an another type an exception will be thrown.
5654  */
5655 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
5656 {
5657   checkCoherency();
5658   int spaceDim=getSpaceDimension();
5659   int meshDim=getMeshDimension();
5660   if(spaceDim!=3)
5661     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
5662   if(meshDim!=2)
5663     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
5664   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5665   ret->setMesh(this);
5666   int nbOfCells=getNumberOfCells();
5667   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5668   arr->alloc(nbOfCells,1);
5669   double *pt=arr->getPointer();
5670   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5671   const int *conn=_nodal_connec->getConstPointer();
5672   const int *connI=_nodal_connec_index->getConstPointer();
5673   const double *coo=_coords->getConstPointer();
5674   double tmp[12];
5675   for(int i=0;i<nbOfCells;i++,pt++)
5676     {
5677       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5678       switch(t)
5679         {
5680           case INTERP_KERNEL::NORM_QUAD4:
5681             {
5682               FillInCompact3DMode(3,4,conn+1,coo,tmp);
5683               *pt=INTERP_KERNEL::quadSkew(tmp);
5684               break;
5685             }
5686         default:
5687           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
5688         }
5689       conn+=connI[i+1]-connI[i];
5690     }
5691   ret->setName("Skew");
5692   ret->synchronizeTimeWithSupport();
5693   return ret.retn();
5694 }
5695
5696 /*!
5697  * This method aggregate the bbox of each cell and put it into bbox parameter.
5698  * @param bbox out parameter of size 2*spacedim*nbOfcells.
5699  */
5700 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
5701 {
5702   int spaceDim=getSpaceDimension();
5703   int nbOfCells=getNumberOfCells();
5704   bbox.resize(2*nbOfCells*spaceDim);
5705   for(int i=0;i<nbOfCells*spaceDim;i++)
5706     {
5707       bbox[2*i]=std::numeric_limits<double>::max();
5708       bbox[2*i+1]=-std::numeric_limits<double>::max();
5709     }
5710   const double *coordsPtr=_coords->getConstPointer();
5711   const int *conn=_nodal_connec->getConstPointer();
5712   const int *connI=_nodal_connec_index->getConstPointer();
5713   for(int i=0;i<nbOfCells;i++)
5714     {
5715       int offset=connI[i]+1;
5716       int nbOfNodesForCell=connI[i+1]-offset;
5717       for(int j=0;j<nbOfNodesForCell;j++)
5718         {
5719           int nodeId=conn[offset+j];
5720           if(nodeId>=0)
5721             for(int k=0;k<spaceDim;k++)
5722               {
5723                 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
5724                 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
5725               }
5726         }
5727     }
5728 }
5729
5730 /// @cond INTERNAL
5731
5732 namespace ParaMEDMEMImpl
5733 {
5734   class ConnReader
5735   {
5736   public:
5737     ConnReader(const int *c, int val):_conn(c),_val(val) { }
5738     bool operator() (const int& pos) { return _conn[pos]!=_val; }
5739   private:
5740     const int *_conn;
5741     int _val;
5742   };
5743
5744   class ConnReader2
5745   {
5746   public:
5747     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
5748     bool operator() (const int& pos) { return _conn[pos]==_val; }
5749   private:
5750     const int *_conn;
5751     int _val;
5752   };
5753 }
5754
5755 /// @endcond
5756
5757 /*!
5758  * This method expects that 'this' is sorted by types. If not an exception will be thrown.
5759  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
5760  * 'this' is composed in cell types.
5761  * The returned array is of size 3*n where n is the number of different types present in 'this'. 
5762  * For every k in [0,n] ret[3*k+2]==0 because it has no sense here. 
5763  * This parameter is kept only for compatibility with other methode listed above.
5764  */
5765 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
5766 {
5767   checkConnectivityFullyDefined();
5768   const int *conn=_nodal_connec->getConstPointer();
5769   const int *connI=_nodal_connec_index->getConstPointer();
5770   const int *work=connI;
5771   int nbOfCells=getNumberOfCells();
5772   std::size_t n=getAllTypes().size();
5773   std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
5774   std::set<INTERP_KERNEL::NormalizedCellType> types;
5775   for(std::size_t i=0;work!=connI+nbOfCells;i++)
5776     {
5777       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
5778       if(types.find(typ)!=types.end())
5779         {
5780           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
5781           oss << " is not contiguous !";
5782           throw INTERP_KERNEL::Exception(oss.str().c_str());
5783         }
5784       types.insert(typ);
5785       ret[3*i]=typ;
5786       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
5787       ret[3*i+1]=(int)std::distance(work,work2);
5788       work=work2;
5789     }
5790   return ret;
5791 }
5792
5793 /*!
5794  * This method is used to check that this has contiguous cell type in same order than described in 'code'.
5795  * only for types cell, type node is not managed.
5796  * Format of 'code' is the following. 'code' should be of size 3*n and non empty. If not an exception is thrown.
5797  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
5798  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
5799  * If 2 or more same geometric type is in 'code' and exception is thrown too.
5800  *
5801  * This method firstly checks
5802  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
5803  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
5804  * an exception is thrown too.
5805  * 
5806  * If all geometric types in 'code' are exactly those in 'this' null pointer is returned.
5807  * If it exists a geometric type in 'this' \b not in 'code' \b no exception is thrown 
5808  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
5809  */
5810 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
5811 {
5812   if(code.empty())
5813     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
5814   std::size_t sz=code.size();
5815   std::size_t n=sz/3;
5816   if(sz%3!=0)
5817     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
5818   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5819   int nb=0;
5820   for(std::size_t i=0;i<n;i++)
5821     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
5822       {
5823         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
5824         nb+=code[3*i+1];
5825         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
5826           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
5827       }
5828   if(types.size()!=n)
5829     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
5830   if(idsPerType.empty())
5831     {
5832       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
5833         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
5834       if(types.size()==_types.size())
5835         return 0;
5836     }
5837   DataArrayInt *ret=DataArrayInt::New();
5838   ret->alloc(nb,1);
5839   int *retPtr=ret->getPointer();
5840   const int *connI=_nodal_connec_index->getConstPointer();
5841   const int *conn=_nodal_connec->getConstPointer();
5842   int nbOfCells=getNumberOfCells();
5843   const int *i=connI;
5844   int kk=0;
5845   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
5846     {
5847       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
5848       int offset=(int)std::distance(connI,i);
5849       if(code[3*kk+2]==-1)
5850         {
5851           const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
5852           std::size_t pos2=std::distance(i,j);
5853           for(std::size_t k=0;k<pos2;k++)
5854             *retPtr++=(int)k+offset;
5855           i=j;
5856         }
5857       else
5858         {
5859           retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
5860                                 retPtr,std::bind2nd(std::plus<int>(),offset));
5861         }
5862     }
5863   return ret;
5864 }
5865
5866 /*!
5867  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
5868  * 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.
5869  * 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.
5870  * This method has 1 input \a profile and 3 outputs \a code' \a idsInPflPerType and \a idsPerType.
5871  * 
5872  * @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.
5873  * @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,
5874  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
5875  * @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.
5876  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
5877  * @throw if \a profile has not exactly one component. It throws too, if \a profile contains some values not in [0,getNumberOfCells()) or if 'this' is not fully defined
5878  */
5879 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
5880 {
5881   if(profile->getNumberOfComponents()!=1)
5882     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
5883   checkConnectivityFullyDefined();
5884   const int *conn=_nodal_connec->getConstPointer();
5885   const int *connI=_nodal_connec_index->getConstPointer();
5886   int nbOfCells=getNumberOfCells();
5887   std::vector<INTERP_KERNEL::NormalizedCellType> types;
5888   std::vector<int> typeRangeVals(1);
5889   for(const int *i=connI;i!=connI+nbOfCells;)
5890     {
5891       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
5892       if(std::find(types.begin(),types.end(),curType)!=types.end())
5893         {
5894           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
5895         }
5896       types.push_back(curType);
5897       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
5898       typeRangeVals.push_back((int)std::distance(connI,i));
5899     }
5900   //
5901   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
5902   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
5903   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
5904   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
5905   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
5906   //
5907   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
5908   code.resize(3*nbOfCastsFinal);
5909   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
5910   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
5911   for(int i=0;i<nbOfCastsFinal;i++)
5912     {
5913       int castId=castsPresent->getIJ(i,0);
5914       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
5915       idsInPflPerType2.push_back(tmp3);
5916       code[3*i]=(int)types[castId];
5917       code[3*i+1]=tmp3->getNumberOfTuples();
5918       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
5919       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
5920         {
5921           tmp4->copyStringInfoFrom(*profile);
5922           idsPerType2.push_back(tmp4);
5923           code[3*i+2]=(int)idsPerType2.size()-1;
5924         }
5925       else
5926         {
5927           code[3*i+2]=-1;
5928         }
5929     }
5930   std::size_t sz2=idsInPflPerType2.size();
5931   idsInPflPerType.resize(sz2);
5932   for(std::size_t i=0;i<sz2;i++)
5933     {
5934       DataArrayInt *locDa=idsInPflPerType2[i];
5935       locDa->incrRef();
5936       idsInPflPerType[i]=locDa;
5937     }
5938   std::size_t sz=idsPerType2.size();
5939   idsPerType.resize(sz);
5940   for(std::size_t i=0;i<sz;i++)
5941     {
5942       DataArrayInt *locDa=idsPerType2[i];
5943       locDa->incrRef();
5944       idsPerType[i]=locDa;
5945     }
5946 }
5947
5948 /*!
5949  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
5950  * This method make the assumption that 'this' and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
5951  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
5952  * 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.
5953  */
5954 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
5955 {
5956   checkFullyDefined();
5957   nM1LevMesh->checkFullyDefined();
5958   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
5959     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
5960   if(_coords!=nM1LevMesh->getCoords())
5961     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
5962   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
5963   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
5964   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
5965   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
5966   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
5967   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
5968   tmp->setConnectivity(tmp0,tmp1);
5969   tmp->renumberCells(ret0->getConstPointer(),false);
5970   revDesc=tmp->getNodalConnectivity();
5971   revDescIndx=tmp->getNodalConnectivityIndex();
5972   DataArrayInt *ret=0;
5973   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
5974     {
5975       int tmp2;
5976       ret->getMaxValue(tmp2);
5977       ret->decrRef();
5978       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
5979       throw INTERP_KERNEL::Exception(oss.str().c_str());
5980     }
5981   nM1LevMeshIds=ret;
5982   //
5983   revDesc->incrRef();
5984   revDescIndx->incrRef();
5985   ret1->incrRef();
5986   ret0->incrRef();
5987   meshnM1Old2New=ret0;
5988   return ret1;
5989 }
5990
5991 /*!
5992  * This method sorts cell in this so that cells are sorted by cell type specified by MEDMEM and so for MED file.
5993  * It avoids to deal with renum in MEDLoader so it is useful for MED file R/W with multi types.
5994  * This method returns a newly allocated array old2New.
5995  * This method expects that connectivity of this is set. If not an exception will be thrown. Coordinates are not taken into account.
5996  */
5997 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
5998 {
5999   checkConnectivityFullyDefined();
6000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6001   renumberCells(ret->getConstPointer(),false);
6002   return ret.retn();
6003 }
6004
6005 /*!
6006  * This methods checks that cells are sorted by their types.
6007  * This method makes asumption (no check) that connectivity is correctly set before calling.
6008  */
6009 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6010 {
6011   checkFullyDefined();
6012   const int *conn=_nodal_connec->getConstPointer();
6013   const int *connI=_nodal_connec_index->getConstPointer();
6014   int nbOfCells=getNumberOfCells();
6015   std::set<INTERP_KERNEL::NormalizedCellType> types;
6016   for(const int *i=connI;i!=connI+nbOfCells;)
6017     {
6018       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6019       if(types.find(curType)!=types.end())
6020         return false;
6021       types.insert(curType);
6022       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6023     }
6024   return true;
6025 }
6026
6027 /*!
6028  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6029  * The geometric type order is specified by MED file.
6030  * 
6031  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6032  */
6033 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6034 {
6035   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6036 }
6037
6038 /*!
6039  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6040  * that the order is specified in array defined by [orderBg,orderEnd).
6041  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6042  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6043  */
6044 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6045 {
6046   checkFullyDefined();
6047   const int *conn=_nodal_connec->getConstPointer();
6048   const int *connI=_nodal_connec_index->getConstPointer();
6049   int nbOfCells=getNumberOfCells();
6050   if(nbOfCells==0)
6051     return true;
6052   int lastPos=-1;
6053   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6054   for(const int *i=connI;i!=connI+nbOfCells;)
6055     {
6056       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6057       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6058       if(isTypeExists!=orderEnd)
6059         {
6060           int pos=(int)std::distance(orderBg,isTypeExists);
6061           if(pos<=lastPos)
6062             return false;
6063           lastPos=pos;
6064           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6065         }
6066       else
6067         {
6068           if(sg.find(curType)==sg.end())
6069             {
6070               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6071               sg.insert(curType);
6072             }
6073           else
6074             return false;
6075         }
6076     }
6077   return true;
6078 }
6079
6080 /*!
6081  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6082  * 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
6083  * 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'.
6084  */
6085 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6086 {
6087   checkConnectivityFullyDefined();
6088   int nbOfCells=getNumberOfCells();
6089   const int *conn=_nodal_connec->getConstPointer();
6090   const int *connI=_nodal_connec_index->getConstPointer();
6091   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6092   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6093   tmpa->alloc(nbOfCells,1);
6094   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6095   tmpb->fillWithZero();
6096   int *tmp=tmpa->getPointer();
6097   int *tmp2=tmpb->getPointer();
6098   for(const int *i=connI;i!=connI+nbOfCells;i++)
6099     {
6100       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6101       if(where!=orderEnd)
6102         {
6103           int pos=(int)std::distance(orderBg,where);
6104           tmp2[pos]++;
6105           tmp[std::distance(connI,i)]=pos;
6106         }
6107       else
6108         {
6109           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6110           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6111           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6112           throw INTERP_KERNEL::Exception(oss.str().c_str());
6113         }
6114     }
6115   nbPerType=tmpb.retn();
6116   return tmpa.retn();
6117 }
6118
6119 /*!
6120  * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specfied by [orderBg,orderEnd) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in 'this'.
6121  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6122  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6123  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6124  */
6125 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6126 {
6127   DataArrayInt *nbPerType=0;
6128   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6129   nbPerType->decrRef();
6130   return tmpa->buildPermArrPerLevel();
6131 }
6132
6133 /*!
6134  * This method reorganize the cells of 'this' so that the cells with same geometric types are put together.
6135  * The number of cells remains unchanged after the call of this method.
6136  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6137  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6138  *
6139  * @return the array giving the correspondance old to new.
6140  */
6141 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6142 {
6143   checkFullyDefined();
6144   computeTypes();
6145   const int *conn=_nodal_connec->getConstPointer();
6146   const int *connI=_nodal_connec_index->getConstPointer();
6147   int nbOfCells=getNumberOfCells();
6148   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6149   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6150     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6151       {
6152         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6153         types.push_back(curType);
6154         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6155       }
6156   DataArrayInt *ret=DataArrayInt::New();
6157   ret->alloc(nbOfCells,1);
6158   int *retPtr=ret->getPointer();
6159   std::fill(retPtr,retPtr+nbOfCells,-1);
6160   int newCellId=0;
6161   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6162     {
6163       for(const int *i=connI;i!=connI+nbOfCells;i++)
6164         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6165           retPtr[std::distance(connI,i)]=newCellId++;
6166     }
6167   renumberCells(retPtr,false);
6168   return ret;
6169 }
6170
6171 /*!
6172  * This method splits 'this' into as mush as untructured meshes that consecutive set of same type cells.
6173  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6174  * This method makes asumption that connectivity is correctly set before calling.
6175  */
6176 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6177 {
6178   checkFullyDefined();
6179   const int *conn=_nodal_connec->getConstPointer();
6180   const int *connI=_nodal_connec_index->getConstPointer();
6181   int nbOfCells=getNumberOfCells();
6182   std::vector<MEDCouplingUMesh *> ret;
6183   for(const int *i=connI;i!=connI+nbOfCells;)
6184     {
6185       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6186       int beginCellId=(int)std::distance(connI,i);
6187       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6188       int endCellId=(int)std::distance(connI,i);
6189       int sz=endCellId-beginCellId;
6190       int *cells=new int[sz];
6191       for(int j=0;j<sz;j++)
6192         cells[j]=beginCellId+j;
6193       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6194       delete [] cells;
6195       ret.push_back(m);
6196     }
6197   return ret;
6198 }
6199
6200 /*!
6201  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6202  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6203  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6204  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6205  * are not used here to avoid the build of big permutation array.
6206  *
6207  * \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
6208  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6209  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6210  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6211  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6212  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6213  * \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
6214  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6215  */
6216 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6217                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6218                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6219 {
6220   std::vector<const MEDCouplingUMesh *> ms2;
6221   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6222     if(*it)
6223       {
6224         (*it)->checkConnectivityFullyDefined();
6225         ms2.push_back(*it);
6226       }
6227   if(ms2.empty())
6228     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6229   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6230   int meshDim=ms2[0]->getMeshDimension();
6231   std::vector<const MEDCouplingUMesh *> m1ssm;
6232   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6233   //
6234   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6235   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6236   int fake=0,rk=0;
6237   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6238   ret1->alloc(0,1); ret2->alloc(0,1);
6239   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6240     {
6241       if(meshDim!=(*it)->getMeshDimension())
6242         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6243       if(refCoo!=(*it)->getCoords())
6244         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6245       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6246       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6247       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6248       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6249         {
6250           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6251           m1ssmSingleAuto.push_back(singleCell);
6252           m1ssmSingle.push_back(singleCell);
6253           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6254         }
6255     }
6256   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6257   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6258   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6259   for(std::size_t i=0;i<m1ssm.size();i++)
6260     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6261   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6262   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6263   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6264   return ret0.retn();
6265 }
6266
6267 /*!
6268  * This method returns a newly created DataArrayInt instance.
6269  * This method retrieves cell ids in [begin,end) that have the type 'type'.
6270  */
6271 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6272 {
6273   checkFullyDefined();
6274   const int *conn=_nodal_connec->getConstPointer();
6275   const int *connIndex=_nodal_connec_index->getConstPointer();
6276   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6277   for(const int *w=begin;w!=end;w++)
6278     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6279       ret->pushBackSilent(*w);
6280   return ret.retn();
6281 }
6282
6283 /*!
6284  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6285  * are in [0:getNumberOfCells())
6286  */
6287 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6288 {
6289   checkFullyDefined();
6290   const int *conn=_nodal_connec->getConstPointer();
6291   const int *connI=_nodal_connec_index->getConstPointer();
6292   int nbOfCells=getNumberOfCells();
6293   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6294   int *tmp=new int[nbOfCells];
6295   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6296     {
6297       int j=0;
6298       for(const int *i=connI;i!=connI+nbOfCells;i++)
6299         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6300           tmp[std::distance(connI,i)]=j++;
6301     }
6302   DataArrayInt *ret=DataArrayInt::New();
6303   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6304   ret->copyStringInfoFrom(*da);
6305   int *retPtr=ret->getPointer();
6306   const int *daPtr=da->getConstPointer();
6307   int nbOfElems=da->getNbOfElems();
6308   for(int k=0;k<nbOfElems;k++)
6309     retPtr[k]=tmp[daPtr[k]];
6310   delete [] tmp;
6311   return ret;
6312 }
6313
6314 /*!
6315  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6316  * This method \b works \b for mesh sorted by type.
6317  * cells whose ids is in 'idsPerGeoType' array.
6318  * This method conserves coords and name of mesh.
6319  */
6320 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6321 {
6322   std::vector<int> code=getDistributionOfTypes();
6323   std::size_t nOfTypesInThis=code.size()/3;
6324   int sz=0,szOfType=0;
6325   for(std::size_t i=0;i<nOfTypesInThis;i++)
6326     {
6327       if(code[3*i]!=type)
6328         sz+=code[3*i+1];
6329       else
6330         szOfType=code[3*i+1];
6331     }
6332   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6333     if(*work<0 || *work>=szOfType)
6334       {
6335         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6336         oss << ". It should be in [0," << szOfType << ") !";
6337         throw INTERP_KERNEL::Exception(oss.str().c_str());
6338       }
6339   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6340   int *idsPtr=idsTokeep->getPointer();
6341   int offset=0;
6342   for(std::size_t i=0;i<nOfTypesInThis;i++)
6343     {
6344       if(code[3*i]!=type)
6345         for(int j=0;j<code[3*i+1];j++)
6346           *idsPtr++=offset+j;
6347       else
6348         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6349       offset+=code[3*i+1];
6350     }
6351   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6352   ret->copyTinyInfoFrom(this);
6353   return ret.retn();
6354 }
6355
6356 /*!
6357  * This method returns a vector of size 'this->getNumberOfCells()'.
6358  * This method retrieves for each cell in 'this' if it is linear (false) or quadratic(true).
6359  */
6360 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6361 {
6362   int ncell=getNumberOfCells();
6363   std::vector<bool> ret(ncell);
6364   const int *cI=getNodalConnectivityIndex()->getConstPointer();
6365   const int *c=getNodalConnectivity()->getConstPointer();
6366   for(int i=0;i<ncell;i++)
6367     {
6368       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6369       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6370       ret[i]=cm.isQuadratic();
6371     }
6372   return ret;
6373 }
6374
6375 /*!
6376  * Returns a newly created mesh (with ref count ==1) that contains merge of 'this' and 'other'.
6377  */
6378 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6379 {
6380   if(other->getType()!=UNSTRUCTURED)
6381     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6382   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6383   return MergeUMeshes(this,otherC);
6384 }
6385
6386 /*!
6387  * This method is ** very badly named ** : This method computes the center of inertia of each cells in \a this.
6388  * So this method is not a right choice for degnerated meshes (not well oriented, cells with measure close to zero).
6389  *
6390  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
6391  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
6392  * 
6393  * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6394  */
6395 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6396 {
6397   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6398   int spaceDim=getSpaceDimension();
6399   int nbOfCells=getNumberOfCells();
6400   ret->alloc(nbOfCells,spaceDim);
6401   ret->copyStringInfoFrom(*getCoords());
6402   double *ptToFill=ret->getPointer();
6403   const int *nodal=_nodal_connec->getConstPointer();
6404   const int *nodalI=_nodal_connec_index->getConstPointer();
6405   const double *coor=_coords->getConstPointer();
6406   for(int i=0;i<nbOfCells;i++)
6407     {
6408       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6409       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6410       ptToFill+=spaceDim;
6411     }
6412   return ret.retn();
6413 }
6414
6415 /*!
6416  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
6417  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
6418  * 
6419  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
6420  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
6421  * 
6422  * \sa MEDCouplingUMesh::getBarycenterAndOwner
6423  * \throw If \a this is not fully defined (coordinates and connectivity)
6424  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
6425  */
6426 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
6427 {
6428   checkFullyDefined();
6429   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6430   int spaceDim=getSpaceDimension();
6431   int nbOfCells=getNumberOfCells();
6432   int nbOfNodes=getNumberOfNodes();
6433   ret->alloc(nbOfCells,spaceDim);
6434   double *ptToFill=ret->getPointer();
6435   const int *nodal=_nodal_connec->getConstPointer();
6436   const int *nodalI=_nodal_connec_index->getConstPointer();
6437   const double *coor=_coords->getConstPointer();
6438   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
6439     {
6440       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6441       std::fill(ptToFill,ptToFill+spaceDim,0.);
6442       if(type!=INTERP_KERNEL::NORM_POLYHED)
6443         {
6444           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
6445             {
6446               if(*conn>=0 && *conn<nbOfNodes)
6447                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
6448               else
6449                 {
6450                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
6451                   throw INTERP_KERNEL::Exception(oss.str().c_str());
6452                 }
6453             }
6454           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
6455           if(nbOfNodesInCell>0)
6456             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
6457           else
6458             {
6459               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
6460               throw INTERP_KERNEL::Exception(oss.str().c_str());
6461             }
6462         }
6463       else
6464         {
6465           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
6466           s.erase(-1);
6467           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
6468             {
6469               if(*it>=0 && *it<nbOfNodes)
6470                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
6471               else
6472                 {
6473                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
6474                   throw INTERP_KERNEL::Exception(oss.str().c_str());
6475                 }
6476             }
6477           if(!s.empty())
6478             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
6479           else
6480             {
6481               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
6482               throw INTERP_KERNEL::Exception(oss.str().c_str());
6483             }
6484         }
6485     }
6486   return ret.retn();
6487 }
6488
6489 /*!
6490  * This method is similar to MEDCouplingUMesh::getBarycenterAndOwner except that it works on subPart of 'this' without
6491  * building explicitely it. The input part is defined by an array [begin,end). All ids contained in this array should be less than this->getNumberOfCells().
6492  * No check of that will be done !
6493  */
6494 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
6495 {
6496   DataArrayDouble *ret=DataArrayDouble::New();
6497   int spaceDim=getSpaceDimension();
6498   int nbOfTuple=(int)std::distance(begin,end);
6499   ret->alloc(nbOfTuple,spaceDim);
6500   double *ptToFill=ret->getPointer();
6501   double *tmp=new double[spaceDim];
6502   const int *nodal=_nodal_connec->getConstPointer();
6503   const int *nodalI=_nodal_connec_index->getConstPointer();
6504   const double *coor=_coords->getConstPointer();
6505   for(const int *w=begin;w!=end;w++)
6506     {
6507       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
6508       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
6509       ptToFill+=spaceDim;
6510     }
6511   delete [] tmp;
6512   return ret;
6513 }
6514
6515 /*!
6516  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
6517  * 
6518  */
6519 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
6520 {
6521   if(!da)
6522     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
6523   da->checkAllocated();
6524   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
6525   ret->setCoords(da);
6526   int nbOfTuples=da->getNumberOfTuples();
6527   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
6528   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
6529   c->alloc(2*nbOfTuples,1);
6530   cI->alloc(nbOfTuples+1,1);
6531   int *cp=c->getPointer();
6532   int *cip=cI->getPointer();
6533   *cip++=0;
6534   for(int i=0;i<nbOfTuples;i++)
6535     {
6536       *cp++=INTERP_KERNEL::NORM_POINT1;
6537       *cp++=i;
6538       *cip++=2*(i+1);
6539     }
6540   ret->setConnectivity(c,cI,true);
6541   return ret.retn();
6542 }
6543
6544 /*!
6545  * Returns a newly created mesh (with ref count ==1) that contains merge of 'mesh1' and 'other'.
6546  * The coords of 'mesh2' are added at the end of coords of 'mesh1'.
6547  */
6548 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
6549 {
6550   std::vector<const MEDCouplingUMesh *> tmp(2);
6551   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
6552   return MergeUMeshes(tmp);
6553 }
6554
6555 /*!
6556  * This method returns in case of success a mesh constitued from union of all meshes in 'a'.
6557  * There should be \b no presence of null pointer into 'a'. If any an INTERP_KERNEL::Exception will be thrown.
6558  * The returned mesh will contain aggregation of nodes in 'a' (in the same order) and aggregation of
6559  * cells in meshes in 'a' (in the same order too).
6560  */
6561 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
6562 {
6563   std::size_t sz=a.size();
6564   if(sz==0)
6565     return MergeUMeshesLL(a);
6566   for(std::size_t ii=0;ii<sz;ii++)
6567     if(!a[ii])
6568       {
6569         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
6570         throw INTERP_KERNEL::Exception(oss.str().c_str());
6571       }
6572   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
6573   std::vector< const MEDCouplingUMesh * > aa(sz);
6574   int spaceDim=-3;
6575   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
6576     {
6577       const MEDCouplingUMesh *cur=a[i];
6578       const DataArrayDouble *coo=cur->getCoords();
6579       if(coo)
6580         spaceDim=coo->getNumberOfComponents();
6581     }
6582   if(spaceDim==-3)
6583     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
6584   for(std::size_t i=0;i<sz;i++)
6585     {
6586       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
6587       aa[i]=bb[i];
6588     }
6589   return MergeUMeshesLL(aa);
6590 }
6591
6592 /// @cond INTERNAL
6593
6594 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
6595 {
6596   if(a.empty())
6597     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
6598   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
6599   int meshDim=(*it)->getMeshDimension();
6600   int nbOfCells=(*it)->getNumberOfCells();
6601   int meshLgth=(*it++)->getMeshLength();
6602   for(;it!=a.end();it++)
6603     {
6604       if(meshDim!=(*it)->getMeshDimension())
6605         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
6606       nbOfCells+=(*it)->getNumberOfCells();
6607       meshLgth+=(*it)->getMeshLength();
6608     }
6609   std::vector<const MEDCouplingPointSet *> aps(a.size());
6610   std::copy(a.begin(),a.end(),aps.begin());
6611   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
6612   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
6613   ret->setCoords(pts);
6614   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
6615   c->alloc(meshLgth,1);
6616   int *cPtr=c->getPointer();
6617   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
6618   cI->alloc(nbOfCells+1,1);
6619   int *cIPtr=cI->getPointer();
6620   *cIPtr++=0;
6621   int offset=0;
6622   int offset2=0;
6623   for(it=a.begin();it!=a.end();it++)
6624     {
6625       int curNbOfCell=(*it)->getNumberOfCells();
6626       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
6627       const int *curC=(*it)->_nodal_connec->getConstPointer();
6628       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
6629       for(int j=0;j<curNbOfCell;j++)
6630         {
6631           const int *src=curC+curCI[j];
6632           *cPtr++=*src++;
6633           for(;src!=curC+curCI[j+1];src++,cPtr++)
6634             {
6635               if(*src!=-1)
6636                 *cPtr=*src+offset2;
6637               else
6638                 *cPtr=-1;
6639             }
6640         }
6641       offset+=curCI[curNbOfCell];
6642       offset2+=(*it)->getNumberOfNodes();
6643     }
6644   //
6645   ret->setConnectivity(c,cI,true);
6646   return ret.retn();
6647 }
6648
6649 /// @endcond
6650
6651 /*!
6652  * Idem MergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
6653  * 'meshes' must be a non empty vector.
6654  */
6655 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
6656 {
6657   std::vector<const MEDCouplingUMesh *> tmp(2);
6658   tmp[0]=mesh1; tmp[1]=mesh2;
6659   return MergeUMeshesOnSameCoords(tmp);
6660 }
6661
6662 /*!
6663  * Idem MergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
6664  * 'meshes' must be a non empty vector.
6665  */
6666 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
6667 {
6668   if(meshes.empty())
6669     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
6670   for(std::size_t ii=0;ii<meshes.size();ii++)
6671     if(!meshes[ii])
6672       {
6673         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
6674         throw INTERP_KERNEL::Exception(oss.str().c_str());
6675       }
6676   const DataArrayDouble *coords=meshes.front()->getCoords();
6677   int meshDim=meshes.front()->getMeshDimension();
6678   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
6679   int meshLgth=0;
6680   int meshIndexLgth=0;
6681   for(;iter!=meshes.end();iter++)
6682     {
6683       if(coords!=(*iter)->getCoords())
6684         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
6685       if(meshDim!=(*iter)->getMeshDimension())
6686         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
6687       meshLgth+=(*iter)->getMeshLength();
6688       meshIndexLgth+=(*iter)->getNumberOfCells();
6689     }
6690   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
6691   nodal->alloc(meshLgth,1);
6692   int *nodalPtr=nodal->getPointer();
6693   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
6694   nodalIndex->alloc(meshIndexLgth+1,1);
6695   int *nodalIndexPtr=nodalIndex->getPointer();
6696   int offset=0;
6697   for(iter=meshes.begin();iter!=meshes.end();iter++)
6698     {
6699       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
6700       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
6701       int nbOfCells=(*iter)->getNumberOfCells();
6702       int meshLgth2=(*iter)->getMeshLength();
6703       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
6704       if(iter!=meshes.begin())
6705         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
6706       else
6707         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
6708       offset+=meshLgth2;
6709     }
6710   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
6711   ret->setName("merge");
6712   ret->setMeshDimension(meshDim);
6713   ret->setConnectivity(nodal,nodalIndex,true);
6714   ret->setCoords(coords);
6715   return ret;
6716 }
6717
6718 /*!
6719  * This method fuses meshes 'meshes' and returns the fused mesh and the correspondances arrays for each mesh in 'meshes' in returned mesh.
6720  * If a same cell is detected in several meshes in 'meshes', this cell will appear only once in returned mesh (see ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer for more details)
6721  *
6722  * @param meshes input non empty vector containing meshes having same coordiantes array and same mesh dimension.
6723  * @param compType see MEDCouplingUMesh::zipConnectivityTraducer
6724  * @param corr output vector with same size as 'meshes' parameter. corr[i] is the correspondance array of mesh meshes[i] in returned mesh.
6725  *             The arrays contained in 'corr' parameter are returned with refcounter set to one.
6726  *             To avoid memory leaks the caller have to deal with each instances of DataArrayInt contained in 'corr' parameter.
6727  * @return The mesh lying on the same coordinates than those in meshes. All cells in 'meshes' are in returned mesh with 
6728  * @exception if meshes is a empty vector or meshes are not lying on same coordinates or meshes not have the same dimension.
6729  */
6730 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
6731 {
6732   //All checks are delegated to MergeUMeshesOnSameCoords
6733   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
6734   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
6735   corr.resize(meshes.size());
6736   std::size_t nbOfMeshes=meshes.size();
6737   int offset=0;
6738   const int *o2nPtr=o2n->getConstPointer();
6739   for(std::size_t i=0;i<nbOfMeshes;i++)
6740     {
6741       DataArrayInt *tmp=DataArrayInt::New();
6742       int curNbOfCells=meshes[i]->getNumberOfCells();
6743       tmp->alloc(curNbOfCells,1);
6744       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
6745       offset+=curNbOfCells;
6746       tmp->setName(meshes[i]->getName());
6747       corr[i]=tmp;
6748     }
6749   return ret.retn();
6750 }
6751
6752 /*!
6753  * This method takes in input meshes \b meshes containing no null reference. If any an INTERP_KERNEL::Exception will be thrown.
6754  * \b meshes should have a good coherency (connectivity and coordinates well defined).
6755  * All mesh in \b meshes must have the same space dimension. If not an INTERP_KERNEL:Exception will be thrown.
6756  * But mesh in \b meshes \b can \b have \b different \b mesh \b dimension \b each \b other.
6757  *
6758  * This method performs nothing if size of \b meshes is in [0,1].
6759  * This method is particulary useful in MEDLoader context to build a \ref ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
6760  * coordinates DataArrayDouble instance.
6761  *
6762  * \param [in,out] meshes : vector containing no null instance of MEDCouplingUMesh that in case of success of this method will be modified.
6763  */
6764 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
6765 {
6766   std::size_t sz=meshes.size();
6767   if(sz==0 || sz==1)
6768     return;
6769   std::vector< const DataArrayDouble * > coords(meshes.size());
6770   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
6771   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
6772     {
6773       if((*it))
6774         {
6775           (*it)->checkConnectivityFullyDefined();
6776           const DataArrayDouble *coo=(*it)->getCoords();
6777           if(coo)
6778             *it2=coo;
6779           else
6780             {
6781               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6782               oss << " has no coordinate array defined !";
6783               throw INTERP_KERNEL::Exception(oss.str().c_str());
6784             }
6785         }
6786       else
6787         {
6788           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
6789           oss << " is null !";
6790           throw INTERP_KERNEL::Exception(oss.str().c_str());
6791         }
6792     }
6793   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
6794   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
6795   int offset=(*it)->getNumberOfNodes();
6796   (*it++)->setCoords(res);
6797   for(;it!=meshes.end();it++)
6798     {
6799       int oldNumberOfNodes=(*it)->getNumberOfNodes();
6800       (*it)->setCoords(res);
6801       (*it)->shiftNodeNumbersInConn(offset);
6802       offset+=oldNumberOfNodes;
6803     }
6804 }
6805
6806 /*!
6807  * This method takes in input meshes \b meshes containing no null reference. If any an INTERP_KERNEL::Exception will be thrown.
6808  * \b meshes should have a good coherency (connectivity and coordinates well defined).
6809  * All mesh in \b meshes must have the same space dimension. If not an INTERP_KERNEL:Exception will be thrown.
6810  * But mesh in \b meshes \b can \b have \b different \b mesh \b dimension \b each \b other.
6811  * If \b meshes share the same instance of DataArrayDouble as coordinates and that this instance is null, this method do nothing and no exception will be thrown.
6812  *
6813  * This method performs nothing if size of \b meshes is empty.
6814  * This method is particulary useful in MEDLoader context to perform a treatment of a MEDFileUMesh instance on different levels.
6815  * coordinates DataArrayDouble instance.
6816  *
6817  * \param [in,out] meshes :vector containing no null instance of MEDCouplingUMesh sharing the same DataArrayDouble instance of coordinates, that in case of success of this method will be modified.
6818  * \param [in] eps is the distance in absolute (that should be positive !), so that 2 or more points within a distance of eps will be merged into a single point.
6819  */
6820 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
6821 {
6822   if(meshes.empty())
6823     return ;
6824   std::set<const DataArrayDouble *> s;
6825   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6826     {
6827       if(*it)
6828         s.insert((*it)->getCoords());
6829       else
6830         {
6831           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 !";
6832           throw INTERP_KERNEL::Exception(oss.str().c_str());
6833         }
6834     }
6835   if(s.size()!=1)
6836     {
6837       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 !";
6838       throw INTERP_KERNEL::Exception(oss.str().c_str());
6839     }
6840   const DataArrayDouble *coo=*(s.begin());
6841   if(!coo)
6842     return;
6843   //
6844   DataArrayInt *comm,*commI;
6845   coo->findCommonTuples(eps,-1,comm,commI);
6846   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
6847   int oldNbOfNodes=coo->getNumberOfTuples();
6848   int newNbOfNodes;
6849   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
6850   if(oldNbOfNodes==newNbOfNodes)
6851     return ;
6852   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
6853   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
6854     {
6855       (*it)->renumberNodesInConn(o2n->getConstPointer());
6856       (*it)->setCoords(newCoords);
6857     } 
6858 }
6859
6860 /*!
6861  * This method takes in input a cell defined by its MEDcouplingUMesh connectivity [connBg,connEnd) and returns its extruded cell by inserting the result at the end of ret.
6862  * @param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
6863  * @param isQuad specifies the policy of connectivity.
6864  * @ret in/out parameter in which the result will be append
6865  */
6866 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
6867 {
6868   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
6869   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
6870   ret.push_back(cm.getExtrudedType());
6871   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
6872   switch(flatType)
6873     {
6874     case INTERP_KERNEL::NORM_POINT1:
6875       {
6876         ret.push_back(connBg[1]);
6877         ret.push_back(connBg[1]+nbOfNodesPerLev);
6878         break;
6879       }
6880     case INTERP_KERNEL::NORM_SEG2:
6881       {
6882         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
6883         ret.insert(ret.end(),conn,conn+4);
6884         break;
6885       }
6886     case INTERP_KERNEL::NORM_SEG3:
6887       {
6888         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
6889         ret.insert(ret.end(),conn,conn+8);
6890         break;
6891       }
6892     case INTERP_KERNEL::NORM_QUAD4:
6893       {
6894         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
6895         ret.insert(ret.end(),conn,conn+8);
6896         break;
6897       }
6898     case INTERP_KERNEL::NORM_TRI3:
6899       {
6900         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
6901         ret.insert(ret.end(),conn,conn+6);
6902         break;
6903       }
6904     case INTERP_KERNEL::NORM_TRI6:
6905       {
6906         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,
6907                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
6908         ret.insert(ret.end(),conn,conn+15);
6909         break;
6910       }
6911     case INTERP_KERNEL::NORM_QUAD8:
6912       {
6913         int conn[20]={
6914           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
6915           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
6916           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
6917         };
6918         ret.insert(ret.end(),conn,conn+20);
6919         break;
6920       }
6921     case INTERP_KERNEL::NORM_POLYGON:
6922       {
6923         std::back_insert_iterator< std::vector<int> > ii(ret);
6924         std::copy(connBg+1,connEnd,ii);
6925         *ii++=-1;
6926         std::reverse_iterator<const int *> rConnBg(connEnd);
6927         std::reverse_iterator<const int *> rConnEnd(connBg+1);
6928         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
6929         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
6930         for(std::size_t i=0;i<nbOfRadFaces;i++)
6931           {
6932             *ii++=-1;
6933             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
6934             std::copy(conn,conn+4,ii);
6935           }
6936         break;
6937       }
6938     default:
6939       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
6940     }
6941 }
6942
6943 /*!
6944  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [begin,end).
6945  */
6946 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
6947 {
6948   double v[3]={0.,0.,0.};
6949   std::size_t sz=std::distance(begin,end);
6950   if(isQuadratic)
6951     sz/=2;
6952   for(std::size_t i=0;i<sz;i++)
6953     {
6954       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];
6955       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
6956       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
6957     }
6958   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
6959 }
6960
6961 /*!
6962  * The polyhedron is specfied by its connectivity nodes in [begin,end).
6963  */
6964 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
6965 {
6966   std::vector<std::pair<int,int> > edges;
6967   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
6968   const int *bgFace=begin;
6969   for(std::size_t i=0;i<nbOfFaces;i++)
6970     {
6971       const int *endFace=std::find(bgFace+1,end,-1);
6972       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
6973       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
6974         {
6975           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
6976           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
6977             return false;
6978           edges.push_back(p1);
6979         }
6980       bgFace=endFace+1;
6981     }
6982   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
6983 }
6984
6985 /*!
6986  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [begin,end).
6987  */
6988 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
6989 {
6990   double vec0[3],vec1[3];
6991   std::size_t sz=std::distance(begin,end);
6992   if(sz%2!=0)
6993     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
6994   int nbOfNodes=(int)sz/2;
6995   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
6996   const double *pt0=coords+3*begin[0];
6997   const double *pt1=coords+3*begin[nbOfNodes];
6998   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
6999   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7000 }
7001
7002 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7003 {
7004   std::size_t sz=std::distance(begin,end);
7005   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7006   std::size_t nbOfNodes(sz/2);
7007   std::copy(begin,end,(int *)tmp);
7008   for(std::size_t j=1;j<nbOfNodes;j++)
7009     {
7010       begin[j]=tmp[nbOfNodes-j];
7011       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7012     }
7013 }
7014
7015 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7016 {
7017   std::size_t sz=std::distance(begin,end);
7018   if(sz!=4)
7019     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7020   double vec0[3],vec1[3];
7021   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7022   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]; 
7023   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;
7024 }
7025
7026 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7027 {
7028   std::size_t sz=std::distance(begin,end);
7029   if(sz!=5)
7030     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7031   double vec0[3];
7032   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7033   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7034   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7035 }
7036
7037 /*!
7038  * 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) 
7039  * 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
7040  * a 2D space.
7041  *
7042  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7043  * \param [in] coords the coordinates with nb of components exactly equal to 3
7044  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7045  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7046  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7047  */
7048 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7049 {
7050   int nbFaces=std::count(begin+1,end,-1)+1;
7051   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7052   double *vPtr=v->getPointer();
7053   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7054   double *pPtr=p->getPointer();
7055   const int *stFaceConn=begin+1;
7056   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7057     {
7058       const int *endFaceConn=std::find(stFaceConn,end,-1);
7059       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7060       stFaceConn=endFaceConn+1;
7061     }
7062   pPtr=p->getPointer(); vPtr=v->getPointer();
7063   DataArrayInt *comm1=0,*commI1=0;
7064   v->findCommonTuples(eps,-1,comm1,commI1);
7065   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7066   const int *comm1Ptr=comm1->getConstPointer();
7067   const int *commI1Ptr=commI1->getConstPointer();
7068   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7069   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7070   //
7071   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7072   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7073   mm->finishInsertingCells();
7074   //
7075   for(int i=0;i<nbOfGrps1;i++)
7076     {
7077       int vecId=comm1Ptr[commI1Ptr[i]];
7078       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7079       DataArrayInt *comm2=0,*commI2=0;
7080       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7081       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7082       const int *comm2Ptr=comm2->getConstPointer();
7083       const int *commI2Ptr=commI2->getConstPointer();
7084       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7085       for(int j=0;j<nbOfGrps2;j++)
7086         {
7087           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7088             {
7089               res->insertAtTheEnd(begin,end);
7090               res->pushBackSilent(-1);
7091             }
7092           else
7093             {
7094               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7095               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7096               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7097               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7098               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7099               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7100               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7101               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7102               const int *idsNodePtr=idsNode->getConstPointer();
7103               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];
7104               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7105               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7106               if(std::abs(norm)>eps)
7107                 {
7108                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7109                   mm3->rotate(center,vec,angle);
7110                 }
7111               mm3->changeSpaceDimension(2);
7112               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7113               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7114               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7115               int nbOfCells=mm4->getNumberOfCells();
7116               for(int k=0;k<nbOfCells;k++)
7117                 {
7118                   int l=0;
7119                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7120                     res->pushBackSilent(idsNodePtr[*work]);
7121                   res->pushBackSilent(-1);
7122                 }
7123             }
7124         }
7125     }
7126   res->popBackSilent();
7127 }
7128
7129 /*!
7130  * 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
7131  * through origin. The plane is defined by its nodal connectivity [\b begin, \b end).
7132  * 
7133  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7134  * \param [in] coords coordinates expected to have 3 components.
7135  * \param [in] begin start of the nodal connectivity of the face.
7136  * \param [in] end end of the nodal connectivity (excluded) of the face.
7137  * \param [out] v the normalized vector of size 3
7138  * \param [out] p the pos of plane
7139  */
7140 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7141 {
7142   std::size_t nbPoints=std::distance(begin,end);
7143   if(nbPoints<3)
7144     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7145   double vec[3];
7146   std::size_t j=0;
7147   bool refFound=false;
7148   for(;j<nbPoints-1 && !refFound;j++)
7149     {
7150       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7151       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7152       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7153       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7154       if(norm>eps)
7155         {
7156           refFound=true;
7157           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7158         }
7159     }
7160   for(std::size_t i=j;i<nbPoints-1;i++)
7161     {
7162       double curVec[3];
7163       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7164       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7165       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7166       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7167       if(norm<eps)
7168         continue;
7169       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7170       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];
7171       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7172       if(norm>eps)
7173         {
7174           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7175           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7176           return ;
7177         }
7178     }
7179   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7180 }
7181
7182 /*!
7183  * This method tries to obtain a well oriented polyhedron.
7184  * If the algorithm fails, an exception will be thrown.
7185  */
7186 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7187 {
7188   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7189   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7190   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7191   isPerm[0]=true;
7192   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7193   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7194   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7195   //
7196   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7197     {
7198       bgFace=begin;
7199       std::size_t smthChanged=0;
7200       for(std::size_t i=0;i<nbOfFaces;i++)
7201         {
7202           endFace=std::find(bgFace+1,end,-1);
7203           nbOfEdgesInFace=std::distance(bgFace,endFace);
7204           if(!isPerm[i])
7205             {
7206               bool b;
7207               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7208                 {
7209                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7210                   std::pair<int,int> p2(p1.second,p1.first);
7211                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7212                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7213                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7214                 }
7215               if(isPerm[i])
7216                 { 
7217                   if(!b)
7218                     std::reverse(bgFace+1,endFace);
7219                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7220                     {
7221                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7222                       std::pair<int,int> p2(p1.second,p1.first);
7223                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7224                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7225                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7226                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7227                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7228                       if(it!=edgesOK.end())
7229                         {
7230                           edgesOK.erase(it);
7231                           edgesFinished.push_back(p1);
7232                         }
7233                       else
7234                         edgesOK.push_back(p1);
7235                     }
7236                 }
7237             }
7238           bgFace=endFace+1;
7239         }
7240       if(smthChanged==0)
7241         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7242     }
7243   if(!edgesOK.empty())
7244     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7245   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7246     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7247       bgFace=begin;
7248       for(std::size_t i=0;i<nbOfFaces;i++)
7249         {
7250           endFace=std::find(bgFace+1,end,-1);
7251           std::reverse(bgFace+1,endFace);
7252           bgFace=endFace+1;
7253         }
7254     }
7255 }
7256
7257 /*!
7258  * This method makes the assumption spacedimension == meshdimension == 2.
7259  * This method works only for linear cells.
7260  * 
7261  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7262  */
7263 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7264 {
7265   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7266     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7267   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7268   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7269   int nbOfNodesExpected=m->getNumberOfNodes();
7270   if(m->getNumberOfCells()!=nbOfNodesExpected)
7271     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7272   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7273   const int *n2oPtr=n2o->getConstPointer();
7274   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7275   m->getReverseNodalConnectivity(revNodal,revNodalI);
7276   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7277   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7278   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7279   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7280   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
7281   if(nbOfNodesExpected<1)
7282     return ret.retn();
7283   int prevCell=0;
7284   int prevNode=nodalPtr[nodalIPtr[0]+1];
7285   *work++=n2oPtr[prevNode];
7286   for(int i=1;i<nbOfNodesExpected;i++)
7287     {
7288       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7289         {
7290           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7291           conn.erase(prevNode);
7292           if(conn.size()==1)
7293             {
7294               int curNode=*(conn.begin());
7295               *work++=n2oPtr[curNode];
7296               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7297               shar.erase(prevCell);
7298               if(shar.size()==1)
7299                 {
7300                   prevCell=*(shar.begin());
7301                   prevNode=curNode;
7302                 }
7303               else
7304                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
7305             }
7306           else
7307             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
7308         }
7309       else
7310         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
7311     }
7312   return ret.retn();
7313 }
7314
7315 /*!
7316  * This method makes the assumption spacedimension == meshdimension == 3.
7317  * This method works only for linear cells.
7318  * 
7319  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7320  */
7321 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
7322 {
7323   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7324     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7325   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7326   const int *conn=m->getNodalConnectivity()->getConstPointer();
7327   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
7328   int nbOfCells=m->getNumberOfCells();
7329   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7330   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
7331   if(nbOfCells<1)
7332     return ret.retn();
7333   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7334   for(int i=1;i<nbOfCells;i++)
7335     {
7336       *work++=-1;
7337       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7338     }
7339   return ret.retn();
7340 }
7341
7342 /*!
7343  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
7344  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
7345  */
7346 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
7347 {
7348   double *w=zipFrmt;
7349   if(spaceDim==3)
7350     for(int i=0;i<nbOfNodesInCell;i++)
7351       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
7352   else if(spaceDim==2)
7353     {
7354       for(int i=0;i<nbOfNodesInCell;i++)
7355         {
7356           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
7357           *w++=0.;
7358         }
7359     }
7360   else
7361     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
7362 }
7363
7364 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
7365 {
7366   int nbOfCells=getNumberOfCells();
7367   if(nbOfCells<=0)
7368     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7369   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,-1,4};
7370   ofs << "  <" << getVTKDataSetType() << ">\n";
7371   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7372   ofs << "      <PointData>\n" << pointData << std::endl;
7373   ofs << "      </PointData>\n";
7374   ofs << "      <CellData>\n" << cellData << std::endl;
7375   ofs << "      </CellData>\n";
7376   ofs << "      <Points>\n";
7377   if(getSpaceDimension()==3)
7378     _coords->writeVTK(ofs,8,"Points");
7379   else
7380     {
7381       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7382       coo->writeVTK(ofs,8,"Points");
7383     }
7384   ofs << "      </Points>\n";
7385   ofs << "      <Cells>\n";
7386   const int *cPtr=_nodal_connec->getConstPointer();
7387   const int *cIPtr=_nodal_connec_index->getConstPointer();
7388   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
7389   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
7390   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
7391   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
7392   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
7393   int szFaceOffsets=0,szConn=0;
7394   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
7395     {
7396       *w2=cPtr[cIPtr[i]];
7397       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
7398         {
7399           *w1=-1;
7400           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
7401           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
7402         }
7403       else
7404         {
7405           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
7406           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
7407           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
7408           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
7409           w4=std::copy(c.begin(),c.end(),w4);
7410         }
7411     }
7412   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
7413   types->writeVTK(ofs,8,"UInt8","types");
7414   offsets->writeVTK(ofs,8,"Int32","offsets");
7415   if(szFaceOffsets!=0)
7416     {//presence of Polyhedra
7417       connectivity->reAlloc(szConn);
7418       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
7419       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
7420       w1=faces->getPointer();
7421       for(int i=0;i<nbOfCells;i++)
7422         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
7423           {
7424             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
7425             *w1++=nbFaces;
7426             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
7427             for(int j=0;j<nbFaces;j++)
7428               {
7429                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
7430                 *w1++=(int)std::distance(w6,w5);
7431                 w1=std::copy(w6,w5,w1);
7432                 w6=w5+1;
7433               }
7434           }
7435       faces->writeVTK(ofs,8,"Int32","faces");
7436     }
7437   connectivity->writeVTK(ofs,8,"Int32","connectivity");
7438   ofs << "      </Cells>\n";
7439   ofs << "    </Piece>\n";
7440   ofs << "  </" << getVTKDataSetType() << ">\n";
7441 }
7442
7443 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
7444 {
7445   stream << "MEDCouplingUMesh C++ instance at " << this << ".";
7446   if(_mesh_dim==-2)
7447     { stream << " Not set !"; return ; }
7448   stream << " Mesh dimension : " << _mesh_dim << ".";
7449   if(_mesh_dim==-1)
7450     return ;
7451   if(!_coords)
7452     { stream << " No coordinates set !"; return ; }
7453   if(!_coords->isAllocated())
7454     { stream << " Coordinates set but not allocated !"; return ; }
7455   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
7456   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
7457   if(!_nodal_connec_index)
7458     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
7459   if(!_nodal_connec_index->isAllocated())
7460     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
7461   int lgth=_nodal_connec_index->getNumberOfTuples();
7462   int cpt=_nodal_connec_index->getNumberOfComponents();
7463   if(cpt!=1 || lgth<1)
7464     return ;
7465   stream << std::endl << "Number of cells : " << lgth-1 << ".";
7466 }
7467
7468 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
7469 {
7470   return std::string("UnstructuredGrid");
7471 }
7472
7473 /// @cond INTERNAL
7474
7475 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
7476 {
7477   m1->checkFullyDefined();
7478   m2->checkFullyDefined();
7479   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
7480     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
7481   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
7482   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
7483   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
7484   std::vector<double> addCoo,addCoordsQuadratic;
7485   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
7486   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
7487   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
7488                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
7489   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
7490   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
7491   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
7492   std::vector< std::vector<int> > intersectEdge2;
7493   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
7494   subDiv2.clear(); dd5=0; dd6=0;
7495   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
7496   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
7497   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
7498                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
7499   //
7500   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
7501   addCooDa->alloc((int)(addCoo.size())/2,2);
7502   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
7503   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
7504   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
7505   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
7506   std::vector<const DataArrayDouble *> coordss(4);
7507   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
7508   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
7509   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
7510   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
7511   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
7512   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
7513   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
7514   ret->setConnectivity(conn,connI,true);
7515   ret->setCoords(coo);
7516   cellNb1=c1.retn(); cellNb2=c2.retn();
7517   return ret.retn();
7518 }
7519
7520 /// @endcond
7521
7522 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
7523                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
7524                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
7525                                                          const std::vector<double>& addCoords,
7526                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
7527 {
7528   static const int SPACEDIM=2;
7529   std::vector<double> bbox1,bbox2;
7530   const double *coo1=m1->getCoords()->getConstPointer();
7531   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
7532   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
7533   int offset1=m1->getNumberOfNodes();
7534   const double *coo2=m2->getCoords()->getConstPointer();
7535   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
7536   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
7537   int offset2=offset1+m2->getNumberOfNodes();
7538   int offset3=offset2+((int)addCoords.size())/2;
7539   m1->getBoundingBoxForBBTree(bbox1);
7540   m2->getBoundingBoxForBBTree(bbox2);
7541   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
7542   int ncell1=m1->getNumberOfCells();
7543   crI.push_back(0);
7544   for(int i=0;i<ncell1;i++)
7545     {
7546       std::vector<int> candidates2;
7547       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
7548       std::map<INTERP_KERNEL::Node *,int> mapp;
7549       std::map<int,INTERP_KERNEL::Node *> mappRev;
7550       INTERP_KERNEL::QuadraticPolygon pol1;
7551       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
7552       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7553       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
7554       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
7555                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
7556       //
7557       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
7558       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
7559       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
7560       for(it1.first();!it1.finished();it1.next())
7561         edges1.insert(it1.current()->getPtr());
7562       //
7563       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
7564       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
7565       int ii=0;
7566       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
7567         {
7568           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
7569           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
7570           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
7571           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
7572                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
7573         }
7574       ii=0;
7575       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
7576         {
7577           pol1.initLocationsWithOther(pol2s[ii]);
7578           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
7579           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
7580           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
7581         }
7582       if(!edges1.empty())
7583         {
7584           try
7585             {
7586               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
7587             }
7588           catch(INTERP_KERNEL::Exception& e)
7589             {
7590               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();
7591               throw INTERP_KERNEL::Exception(oss.str().c_str());
7592             }
7593         }
7594       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
7595         (*it).second->decrRef();
7596     }
7597 }
7598
7599 /*!
7600  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
7601  * 
7602  */
7603 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
7604                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
7605                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
7606                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
7607                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
7608 {
7609   static const int SPACEDIM=2;
7610   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
7611   desc2=DataArrayInt::New();
7612   descIndx2=DataArrayInt::New();
7613   revDesc2=DataArrayInt::New();
7614   revDescIndx2=DataArrayInt::New();
7615   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
7616   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
7617   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
7618   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
7619   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
7620   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
7621   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
7622   std::vector<double> bbox1,bbox2;
7623   m1Desc->getBoundingBoxForBBTree(bbox1);
7624   m2Desc->getBoundingBoxForBBTree(bbox2);
7625   int ncell1=m1Desc->getNumberOfCells();
7626   int ncell2=m2Desc->getNumberOfCells();
7627   intersectEdge1.resize(ncell1);
7628   colinear2.resize(ncell2);
7629   subDiv2.resize(ncell2);
7630   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
7631   std::vector<int> candidates1(1);
7632   int offset1=m1->getNumberOfNodes();
7633   int offset2=offset1+m2->getNumberOfNodes();
7634   for(int i=0;i<ncell1;i++)
7635     {
7636       std::vector<int> candidates2;
7637       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
7638       if(!candidates2.empty())
7639         {
7640           std::map<INTERP_KERNEL::Node *,int> map1,map2;
7641           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
7642           candidates1[0]=i;
7643           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
7644           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
7645           delete pol2;
7646           delete pol1;
7647         }
7648       else
7649         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
7650     }
7651   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
7652   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
7653 }
7654
7655 /*!
7656  * This method performs the 2nd step of Partition of 2D mesh.
7657  * This method has 4 inputs :
7658  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
7659  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
7660  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
7661  * The aim of this method is to sort the splitting nodes, if any, and to put in 'intersectEdge' output paramter based on edges of mesh 'm2'
7662  * @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. Only present for its coords in case of 'subDiv' shares some nodes of 'm1'
7663  * @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.
7664  * @param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
7665  */
7666 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, const std::vector<double>& addCoo, const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge) throw(INTERP_KERNEL::Exception)
7667 {
7668   int offset1=m1->getNumberOfNodes();
7669   int ncell=m2->getNumberOfCells();
7670   const int *c=m2->getNodalConnectivity()->getConstPointer();
7671   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
7672   const double *coo=m2->getCoords()->getConstPointer();
7673   const double *cooBis=m1->getCoords()->getConstPointer();
7674   int offset2=offset1+m2->getNumberOfNodes();
7675   intersectEdge.resize(ncell);
7676   for(int i=0;i<ncell;i++,cI++)
7677     {
7678       const std::vector<int>& divs=subDiv[i];
7679       int nnode=cI[1]-cI[0]-1;
7680       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
7681       std::map<INTERP_KERNEL::Node *, int> mapp22;
7682       for(int j=0;j<nnode;j++)
7683         {
7684           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
7685           int nnid=c[(*cI)+j+1];
7686           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
7687           mapp22[nn]=nnid+offset1;
7688         }
7689       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
7690       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
7691         ((*it).second.first)->decrRef();
7692       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
7693       std::map<INTERP_KERNEL::Node *,int> mapp3;
7694       for(std::size_t j=0;j<divs.size();j++)
7695         {
7696           int id=divs[j];
7697           INTERP_KERNEL::Node *tmp=0;
7698           if(id<offset1)
7699             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
7700           else if(id<offset2)
7701             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
7702           else
7703             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
7704           addNodes[j]=tmp;
7705           mapp3[tmp]=id;
7706         }
7707       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
7708       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
7709         (*it)->decrRef();
7710       e->decrRef();
7711     }
7712 }
7713
7714 /*!
7715  * 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).
7716  * 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
7717  * with a plane. The result will be put in 'cut3DSuf' out parameter.
7718  * @param cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
7719  * @param nodesOnPlane, returns all the nodes that are on the plane.
7720  * @param nodal3DSurf is the nodal connectivity of 3D surf mesh.
7721  * @param nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
7722  * @param nodal3DCurve is the nodal connectivity of 3D curve mesh.
7723  * @param nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
7724  * @param desc is the descending connectivity 3DSurf->3DCurve
7725  * @param descIndx is the descending connectivity index 3DSurf->3DCurve
7726  * @param cut3DSuf input/output param.
7727  */
7728 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
7729                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
7730                                                    const int *desc, const int *descIndx, 
7731                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
7732 {
7733   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
7734   int nbOf3DSurfCell=(int)cut3DSurf.size();
7735   for(int i=0;i<nbOf3DSurfCell;i++)
7736     {
7737       std::vector<int> res;
7738       int offset=descIndx[i];
7739       int nbOfSeg=descIndx[i+1]-offset;
7740       for(int j=0;j<nbOfSeg;j++)
7741         {
7742           int edgeId=desc[offset+j];
7743           int status=cut3DCurve[edgeId];
7744           if(status!=-2)
7745             {
7746               if(status>-1)
7747                 res.push_back(status);
7748               else
7749                 {
7750                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
7751                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
7752                 }
7753             }
7754         }
7755       switch(res.size())
7756         {
7757         case 2:
7758           {
7759             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
7760             break;
7761           }
7762         case 1:
7763         case 0:
7764           {
7765             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
7766             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
7767             if(res.size()==2)
7768               {
7769                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
7770               }
7771             else
7772               {
7773                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
7774               }
7775             break;
7776           }
7777         default:
7778           {// case when plane is on a multi colinear edge of a polyhedron
7779             if((int)res.size()==2*nbOfSeg)
7780               {
7781                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
7782               }
7783             else
7784               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
7785           }
7786         }
7787     }
7788 }
7789
7790 /*!
7791  * 'this' is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
7792  * 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).
7793  * 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
7794  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
7795  * @param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
7796  * @param desc is the descending connectivity 3D->3DSurf
7797  * @param descIndx is the descending connectivity index 3D->3DSurf
7798  */
7799 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
7800                                                   const int *desc, const int *descIndx,
7801                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
7802 {
7803   checkFullyDefined();
7804   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7805     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
7806   const int *nodal3D=_nodal_connec->getConstPointer();
7807   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
7808   int nbOfCells=getNumberOfCells();
7809   for(int i=0;i<nbOfCells;i++)
7810     {
7811       std::map<int, std::set<int> > m;
7812       int offset=descIndx[i];
7813       int nbOfFaces=descIndx[i+1]-offset;
7814       int start=-1;
7815       int end=-1;
7816       for(int j=0;j<nbOfFaces;j++)
7817         {
7818           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
7819           if(p.first!=-1 && p.second!=-1)
7820             {
7821               if(p.first!=-2)
7822                 {
7823                   start=p.first; end=p.second;
7824                   m[p.first].insert(p.second);
7825                   m[p.second].insert(p.first);
7826                 }
7827               else
7828                 {
7829                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
7830                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
7831                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7832                   INTERP_KERNEL::NormalizedCellType cmsId;
7833                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
7834                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
7835                   for(unsigned k=0;k<nbOfNodesSon;k++)
7836                     {
7837                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
7838                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
7839                     }
7840                 }
7841             }
7842         }
7843       if(m.empty())
7844         continue;
7845       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
7846       int prev=end;
7847       while(end!=start)
7848         {
7849           std::map<int, std::set<int> >::const_iterator it=m.find(start);
7850           const std::set<int>& s=(*it).second;
7851           std::set<int> s2; s2.insert(prev);
7852           std::set<int> s3;
7853           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
7854           if(s3.size()==1)
7855             {
7856               int val=*s3.begin();
7857               conn.push_back(start);
7858               prev=start;
7859               start=val;
7860             }
7861           else
7862             start=end;
7863         }
7864       conn.push_back(end);
7865       if(conn.size()>3)
7866         {
7867           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
7868           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
7869           cellIds->pushBackSilent(i);
7870         }
7871     }
7872 }
7873
7874 /*!
7875  * 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
7876  * 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
7877  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
7878  * 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
7879  * 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.
7880  * 
7881  * @return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
7882  */
7883 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
7884 {
7885   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
7886   if(sz>=4)
7887     {
7888       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
7889       if(cm.getDimension()==2)
7890         {
7891           const int *node=nodalConnBg+1;
7892           int startNode=*node++;
7893           double refX=coords[2*startNode];
7894           for(;node!=nodalConnEnd;node++)
7895             {
7896               if(coords[2*(*node)]<refX)
7897                 {
7898                   startNode=*node;
7899                   refX=coords[2*startNode];
7900                 }
7901             }
7902           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
7903           refX=1e300;
7904           double tmp1;
7905           double tmp2[2];
7906           double angle0=-M_PI/2;
7907           //
7908           int nextNode=-1;
7909           int prevNode=-1;
7910           double resRef;
7911           double angleNext;
7912           while(nextNode!=startNode)
7913             {
7914               nextNode=-1;
7915               resRef=1e300;
7916               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
7917                 {
7918                   if(*node!=tmpOut.back() && *node!=prevNode)
7919                     {
7920                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
7921                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
7922                       double res;
7923                       if(angleM<=angle0)
7924                         res=angle0-angleM;
7925                       else
7926                         res=angle0-angleM+2.*M_PI;
7927                       if(res<resRef)
7928                         {
7929                           nextNode=*node;
7930                           resRef=res;
7931                           angleNext=angleM;
7932                         }
7933                     }
7934                 }
7935               if(nextNode!=startNode)
7936                 {
7937                   angle0=angleNext-M_PI;
7938                   if(angle0<-M_PI)
7939                     angle0+=2*M_PI;
7940                   prevNode=tmpOut.back();
7941                   tmpOut.push_back(nextNode);
7942                 }
7943             }
7944           std::vector<int> tmp3(2*(sz-1));
7945           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
7946           std::copy(nodalConnBg+1,nodalConnEnd,it);
7947           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
7948             {
7949               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7950               return false;
7951             }
7952           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
7953             {
7954               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
7955               return false;
7956             }
7957           else
7958             {
7959               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
7960               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
7961               return true;
7962             }
7963         }
7964       else
7965         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7966     }
7967   else
7968     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
7969 }
7970
7971 /*!
7972  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
7973  * 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.
7974  * 
7975  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
7976  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
7977  * \param [in,out] arr array in which the remove operation will be done.
7978  * \param [in,out] arrIndx array in the remove operation will modify
7979  * \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])
7980  * \return true if \b arr and \b arrIndx have been modified, false if not.
7981  */
7982 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
7983 {
7984   if(!arrIndx || !arr)
7985     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
7986   if(offsetForRemoval<0)
7987     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
7988   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
7989   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
7990   int *arrIPtr=arrIndx->getPointer();
7991   *arrIPtr++=0;
7992   int previousArrI=0;
7993   const int *arrPtr=arr->getConstPointer();
7994   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
7995   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
7996     {
7997       if(*arrIPtr-previousArrI>offsetForRemoval)
7998         {
7999           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8000             {
8001               if(s.find(*work)==s.end())
8002                 arrOut.push_back(*work);
8003             }
8004         }
8005       previousArrI=*arrIPtr;
8006       *arrIPtr=(int)arrOut.size();
8007     }
8008   if(arr->getNumberOfTuples()==(int)arrOut.size())
8009     return false;
8010   arr->alloc((int)arrOut.size(),1);
8011   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8012   return true;
8013 }
8014
8015 /*!
8016  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8017  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8018  * The selection of extraction is done standardly in new2old format.
8019  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8020  *
8021  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8022  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8023  * \param [in] arrIn arr origin array from which the extraction will be done.
8024  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8025  * \param [out] arrOut the resulting array
8026  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8027  */
8028 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8029                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8030 {
8031   if(!arrIn || !arrIndxIn)
8032     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8033   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8034   const int *arrInPtr=arrIn->getConstPointer();
8035   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8036   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8037   int maxSizeOfArr=arrIn->getNumberOfTuples();
8038   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8039   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8040   arrIo->alloc((int)(sz+1),1);
8041   const int *idsIt=idsOfSelectBg;
8042   int *work=arrIo->getPointer();
8043   *work++=0;
8044   int lgth=0;
8045   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8046     {
8047       if(*idsIt>=0 && *idsIt<nbOfGrps)
8048         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8049       else
8050         {
8051           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8052           throw INTERP_KERNEL::Exception(oss.str().c_str());
8053         }
8054       if(lgth>=work[-1])
8055         *work=lgth;
8056       else
8057         {
8058           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8059           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8060           throw INTERP_KERNEL::Exception(oss.str().c_str());
8061         }
8062     }
8063   arro->alloc(lgth,1);
8064   work=arro->getPointer();
8065   idsIt=idsOfSelectBg;
8066   for(std::size_t i=0;i<sz;i++,idsIt++)
8067     {
8068       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8069         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8070       else
8071         {
8072           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8073           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8074           throw INTERP_KERNEL::Exception(oss.str().c_str());
8075         }
8076     }
8077   arrOut=arro.retn();
8078   arrIndexOut=arrIo.retn();
8079 }
8080
8081 /*!
8082  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8083  * 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
8084  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8085  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8086  *
8087  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8088  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8089  * \param [in] arrIn arr origin array from which the extraction will be done.
8090  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8091  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8092  * \param [in] srcArrIndex index array of \b srcArr
8093  * \param [out] arrOut the resulting array
8094  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8095  * 
8096  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8097  */
8098 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8099                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8100                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8101 {
8102   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8103     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8104   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8105   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8106   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8107   std::vector<bool> v(nbOfTuples,true);
8108   int offset=0;
8109   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8110   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8111   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8112     {
8113       if(*it>=0 && *it<nbOfTuples)
8114         {
8115           v[*it]=false;
8116           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8117         }
8118       else
8119         {
8120           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8121           throw INTERP_KERNEL::Exception(oss.str().c_str());
8122         }
8123     }
8124   srcArrIndexPtr=srcArrIndex->getConstPointer();
8125   arrIo->alloc(nbOfTuples+1,1);
8126   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8127   const int *arrInPtr=arrIn->getConstPointer();
8128   const int *srcArrPtr=srcArr->getConstPointer();
8129   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8130   int *arroPtr=arro->getPointer();
8131   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8132     {
8133       if(v[ii])
8134         {
8135           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8136           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8137         }
8138       else
8139         {
8140           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8141           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8142           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8143         }
8144     }
8145   arrOut=arro.retn();
8146   arrIndexOut=arrIo.retn();
8147 }
8148
8149 /*!
8150  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8151  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8152  *
8153  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8154  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8155  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8156  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8157  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8158  * \param [in] srcArrIndex index array of \b srcArr
8159  * 
8160  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8161  */
8162 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8163                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8164 {
8165   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8166     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8167   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8168   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8169   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8170   int *arrInOutPtr=arrInOut->getPointer();
8171   const int *srcArrPtr=srcArr->getConstPointer();
8172   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8173     {
8174       if(*it>=0 && *it<nbOfTuples)
8175         {
8176           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8177             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8178           else
8179             {
8180               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] !";
8181               throw INTERP_KERNEL::Exception(oss.str().c_str());
8182             }
8183         }
8184       else
8185         {
8186           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8187           throw INTERP_KERNEL::Exception(oss.str().c_str());
8188         }
8189     }
8190 }
8191
8192 /*!
8193  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8194  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8195  * 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]].
8196  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8197  * A negative value in \b arrIn means that it is ignored.
8198  * 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.
8199  * 
8200  * \param [in] arrIn arr origin array from which the extraction will be done.
8201  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8202  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8203  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8204  */
8205 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
8206 {
8207   int seed=0,nbOfDepthPeelingPerformed=0;
8208   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8209 }
8210
8211 /*!
8212  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8213  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8214  * 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]].
8215  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8216  * A negative value in \b arrIn means that it is ignored.
8217  * 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.
8218  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8219  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8220  * \param [in] arrIn arr origin array from which the extraction will be done.
8221  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8222  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8223  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8224  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8225  * \sa MEDCouplingUMesh::partitionBySpreadZone
8226  */
8227 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8228 {
8229   nbOfDepthPeelingPerformed=0;
8230   if(!arrIndxIn)
8231     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8232   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8233   if(nbOfTuples<=0)
8234     {
8235       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8236       return ret;
8237     }
8238   //
8239   std::vector<bool> fetched(nbOfTuples,false);
8240   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8241 }
8242
8243 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8244 {
8245   nbOfDepthPeelingPerformed=0;
8246   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
8247     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
8248   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8249   std::vector<bool> fetched2(nbOfTuples,false);
8250   int i=0;
8251   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
8252     {
8253       if(*seedElt>=0 && *seedElt<nbOfTuples)
8254         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
8255       else
8256         { 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()); }
8257     }
8258   const int *arrInPtr=arrIn->getConstPointer();
8259   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8260   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
8261   std::vector<int> idsToFetch1(seedBg,seedEnd);
8262   std::vector<int> idsToFetch2;
8263   std::vector<int> *idsToFetch=&idsToFetch1;
8264   std::vector<int> *idsToFetchOther=&idsToFetch2;
8265   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
8266     {
8267       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
8268         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
8269           if(!fetched[*it2])
8270             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
8271       std::swap(idsToFetch,idsToFetchOther);
8272       idsToFetchOther->clear();
8273       nbOfDepthPeelingPerformed++;
8274     }
8275   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
8276   i=0;
8277   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
8278   int *retPtr=ret->getPointer();
8279   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
8280     if(*it)
8281       *retPtr++=i;
8282   return ret.retn();
8283 }
8284
8285 /*!
8286  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8287  * 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
8288  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8289  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8290  *
8291  * \param [in] start begin of set of ids of the input extraction (included)
8292  * \param [in] end end of set of ids of the input extraction (excluded)
8293  * \param [in] step step of the set of ids in range mode.
8294  * \param [in] arrIn arr origin array from which the extraction will be done.
8295  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8296  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8297  * \param [in] srcArrIndex index array of \b srcArr
8298  * \param [out] arrOut the resulting array
8299  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8300  * 
8301  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8302  */
8303 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8304                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8305                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8306 {
8307   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8308     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
8309   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8310   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8311   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8312   int offset=0;
8313   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8314   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8315   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
8316   int it=start;
8317   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8318     {
8319       if(it>=0 && it<nbOfTuples)
8320         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
8321       else
8322         {
8323           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8324           throw INTERP_KERNEL::Exception(oss.str().c_str());
8325         }
8326     }
8327   srcArrIndexPtr=srcArrIndex->getConstPointer();
8328   arrIo->alloc(nbOfTuples+1,1);
8329   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8330   const int *arrInPtr=arrIn->getConstPointer();
8331   const int *srcArrPtr=srcArr->getConstPointer();
8332   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8333   int *arroPtr=arro->getPointer();
8334   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8335     {
8336       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
8337       if(pos<0)
8338         {
8339           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8340           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8341         }
8342       else
8343         {
8344           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8345           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8346         }
8347     }
8348   arrOut=arro.retn();
8349   arrIndexOut=arrIo.retn();
8350 }
8351
8352 /*!
8353  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8354  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8355  *
8356  * \param [in] start begin of set of ids of the input extraction (included)
8357  * \param [in] end end of set of ids of the input extraction (excluded)
8358  * \param [in] step step of the set of ids in range mode.
8359  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8360  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8361  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8362  * \param [in] srcArrIndex index array of \b srcArr
8363  * 
8364  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8365  */
8366 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8367                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8368 {
8369   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8370     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
8371   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8372   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8373   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8374   int *arrInOutPtr=arrInOut->getPointer();
8375   const int *srcArrPtr=srcArr->getConstPointer();
8376   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
8377   int it=start;
8378   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8379     {
8380       if(it>=0 && it<nbOfTuples)
8381         {
8382           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
8383             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
8384           else
8385             {
8386               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
8387               throw INTERP_KERNEL::Exception(oss.str().c_str());
8388             }
8389         }
8390       else
8391         {
8392           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8393           throw INTERP_KERNEL::Exception(oss.str().c_str());
8394         }
8395     }
8396 }
8397
8398 /*!
8399  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
8400  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
8401  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
8402  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
8403  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
8404  * 
8405  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
8406  */
8407 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
8408 {
8409   checkFullyDefined();
8410   int mdim=getMeshDimension();
8411   int spaceDim=getSpaceDimension();
8412   if(mdim!=spaceDim)
8413     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
8414   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
8415   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
8416   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
8417   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
8418   ret->setCoords(getCoords());
8419   ret->allocateCells((int)partition.size());
8420   //
8421   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
8422     {
8423       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
8424       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
8425       switch(mdim)
8426         {
8427         case 2:
8428           cell=tmp->buildUnionOf2DMesh();
8429           break;
8430         case 3:
8431           cell=tmp->buildUnionOf3DMesh();
8432           break;
8433         default:
8434           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
8435         }
8436       
8437       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
8438     }
8439   //
8440   ret->finishInsertingCells();
8441   return ret.retn();
8442 }
8443
8444 /*!
8445  * This method partitions \b this into contiguous zone.
8446  * This method only needs a well defined connectivity. Coordinates are not considered here.
8447  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
8448  */
8449 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
8450 {
8451   //#if 0
8452   int nbOfCellsCur=getNumberOfCells();
8453   std::vector<DataArrayInt *> ret;
8454   if(nbOfCellsCur<=0)
8455     return ret;
8456   DataArrayInt *neigh=0,*neighI=0;
8457   computeNeighborsOfCells(neigh,neighI);
8458   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8459   std::vector<bool> fetchedCells(nbOfCellsCur,false);
8460   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
8461   int seed=0;
8462   while(seed<nbOfCellsCur)
8463     {
8464       int nbOfPeelPerformed=0;
8465       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
8466       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
8467     }
8468   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
8469     ret.push_back((*it).retn());
8470   return ret;
8471   //#endif
8472 #if 0
8473   int nbOfCellsCur=getNumberOfCells();
8474   DataArrayInt *neigh=0,*neighI=0;
8475   computeNeighborsOfCells(neigh,neighI);
8476   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
8477   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
8478   std::vector<DataArrayInt *> ret;
8479   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
8480   while(nbOfCellsCur>0)
8481     {
8482       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
8483       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
8484       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
8485       ret2.push_back(tmp2);  ret.push_back(tmp2);
8486       nbOfCellsCur=tmp3->getNumberOfTuples();
8487       if(nbOfCellsCur>0)
8488         {
8489           ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
8490           MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
8491           neighAuto=neigh;
8492           neighIAuto=neighI;
8493           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
8494           neighAuto->transformWithIndArr(renum->begin(),renum->end());
8495         }
8496     }
8497   for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
8498     (*it)->incrRef();
8499   return ret;
8500 #endif
8501 }
8502
8503 /*!
8504  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
8505  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
8506  *
8507  * \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.
8508  * \return a newly allocated DataArrayInt to be managed by the caller.
8509  * \throw In case of \a code has not the right format (typically of size 3*n)
8510  */
8511 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
8512 {
8513   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
8514   std::size_t nb=code.size()/3;
8515   if(code.size()%3!=0)
8516     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
8517   ret->alloc((int)nb,2);
8518   int *retPtr=ret->getPointer();
8519   for(std::size_t i=0;i<nb;i++,retPtr+=2)
8520     {
8521       retPtr[0]=code[3*i+2];
8522       retPtr[1]=code[3*i+2]+code[3*i+1];
8523     }
8524   return ret.retn();
8525 }
8526
8527 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
8528                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
8529 {
8530   if(mesh)
8531     {
8532       mesh->incrRef();
8533       _nb_cell=mesh->getNumberOfCells();
8534     }
8535 }
8536
8537 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
8538 {
8539   if(_mesh)
8540     _mesh->decrRef();
8541   if(_own_cell)
8542     delete _cell;
8543 }
8544
8545 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
8546                                                                                                                                _own_cell(false),_cell_id(bg-1),
8547                                                                                                                                _nb_cell(end)
8548 {
8549   if(mesh)
8550     mesh->incrRef();
8551 }
8552
8553 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
8554 {
8555   _cell_id++;
8556   if(_cell_id<_nb_cell)
8557     {
8558       _cell->next();
8559       return _cell;
8560     }
8561   else
8562     return 0;
8563 }
8564
8565 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
8566 {
8567   if(_mesh)
8568     _mesh->incrRef();
8569 }
8570
8571 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
8572 {
8573   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
8574 }
8575
8576 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
8577 {
8578   if(_mesh)
8579     _mesh->decrRef();
8580 }
8581
8582 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
8583                                                                                                                                                                   _itc(itc),
8584                                                                                                                                                                   _bg(bg),_end(end)
8585 {
8586   if(_mesh)
8587     _mesh->incrRef();
8588 }
8589
8590 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
8591 {
8592   if(_mesh)
8593     _mesh->decrRef();
8594 }
8595
8596 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
8597 {
8598   return _type;
8599 }
8600
8601 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
8602 {
8603   return _end-_bg;
8604 }
8605
8606 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
8607 {
8608   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
8609 }
8610
8611 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
8612 {
8613   if(mesh)
8614     {
8615       mesh->incrRef();
8616       _nb_cell=mesh->getNumberOfCells();
8617     }
8618 }
8619
8620 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
8621 {
8622   if(_mesh)
8623     _mesh->decrRef();
8624   delete _cell;
8625 }
8626
8627 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
8628 {
8629   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
8630   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
8631   if(_cell_id<_nb_cell)
8632     {
8633       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
8634       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
8635       int startId=_cell_id;
8636       _cell_id+=nbOfElems;
8637       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
8638     }
8639   else
8640     return 0;
8641 }
8642
8643 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
8644 {
8645   if(mesh)
8646     {
8647       _conn=mesh->getNodalConnectivity()->getPointer();
8648       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
8649     }
8650 }
8651
8652 void MEDCouplingUMeshCell::next()
8653 {
8654   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8655     {
8656       _conn+=_conn_lgth;
8657       _conn_indx++;
8658     }
8659   _conn_lgth=_conn_indx[1]-_conn_indx[0];
8660 }
8661
8662 std::string MEDCouplingUMeshCell::repr() const
8663 {
8664   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8665     {
8666       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
8667       oss << " : ";
8668       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
8669       return oss.str();
8670     }
8671   else
8672     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
8673 }
8674
8675 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
8676 {
8677   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8678     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
8679   else
8680     return INTERP_KERNEL::NORM_ERROR;
8681 }
8682
8683 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
8684 {
8685   lgth=_conn_lgth;
8686   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
8687     return _conn;
8688   else
8689     return 0;
8690 }