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