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