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