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